This source file includes following definitions.
- it_char_has_category
- char_can_wrap_before
- char_can_wrap_after
- fill_column_indicator_column
- redisplay_other_windows
- wset_redisplay
- fset_redisplay
- bset_redisplay
- bset_update_mode_line
- wset_update_mode_line
- ATTRIBUTE_FORMAT_PRINTF
- ATTRIBUTE_FORMAT_PRINTF
- window_text_bottom_y
- window_box_width
- window_box_height
- window_box_left_offset
- window_box_right_offset
- window_box_left
- window_box_right
- window_box
- window_box_edges
- line_bottom_y
- DEFUN
- default_line_pixel_height
- string_from_display_spec
- window_hscroll_limited
- reset_box_start_end_flags
- pos_visible_p
- check_char_and_length
- string_pos_nchars_ahead
- string_pos
- c_string_pos
- number_of_chars
- compute_string_pos
- estimate_mode_line_height
- pixel_to_glyph_coords
- x_y_to_hpos_vpos
- frame_to_window_pixel_xy
- get_glyph_string_clip_rects
- get_glyph_string_clip_rect
- get_phys_cursor_geometry
- remember_mouse_glyph
- adjust_window_ends
- hscrolling_current_line_p
- safe_eval_handler
- safe__call
- safe_call
- safe_call1
- safe__call1
- safe_eval
- safe__eval
- safe_call2
- CHECK_IT
- CHECK_WINDOW_END
- init_iterator
- get_narrowed_width
- get_narrowed_len
- get_medium_narrowing_begv
- get_medium_narrowing_zv
- get_nearby_bol_pos
- get_small_narrowing_begv
- get_large_narrowing_begv
- get_large_narrowing_zv
- unwind_narrowed_begv
- start_display
- in_ellipses_for_invisible_text_p
- init_from_display_pos
- init_to_row_start
- init_to_row_end
- handle_stop
- compute_stop_pos
- compute_display_string_pos
- compute_display_string_end
- handle_fontified_prop
- face_at_pos
- handle_face_prop
- underlying_face_id
- face_before_or_after_it_pos
- handle_invisible_prop
- setup_for_ellipsis
- find_display_property
- get_display_property
- display_min_width
- handle_display_prop
- handle_display_spec
- display_prop_end
- handle_single_display_spec
- display_prop_intangible_p
- single_display_spec_string_p
- display_prop_string_p
- string_buffer_position_lim
- string_buffer_position
- handle_composition_prop
- handle_overlay_change
- next_overlay_string
- compare_overlay_entries
- load_overlay_strings
- get_overlay_strings_1
- get_overlay_strings
- push_it
- iterate_out_of_display_property
- restore_face_box_flags
- pop_it
- back_to_previous_line_start
- strings_with_newlines
- forward_to_next_line_start
- back_to_previous_visible_line_start
- reseat_at_previous_visible_line_start
- reseat_at_next_visible_line_start
- reseat
- reseat_1
- reseat_to_string
- lookup_glyphless_char_display
- merge_escape_glyph_face
- merge_glyphless_glyph_face
- forget_escape_and_glyphless_faces
- get_next_display_element
- set_iterator_to_next
- next_element_from_display_vector
- get_visually_first_element
- next_element_from_string
- next_element_from_c_string
- next_element_from_ellipsis
- next_element_from_image
- next_element_from_xwidget
- next_element_from_stretch
- compute_stop_pos_backwards
- handle_stop_backwards
- next_element_from_buffer
- next_element_from_composition
- move_it_in_display_line_to
- move_it_in_display_line
- move_it_to
- move_it_vertically_backward
- move_it_vertically
- move_it_past_eol
- move_it_by_lines
- partial_line_height
- fast_move_it_horizontally
- in_display_vector_p
- window_text_pixel_size
- DEFUN
- format_nargs
- add_to_log
- vadd_to_log
- message_log_maybe_newline
- message_dolog
- message_log_check_duplicate
- message3
- message_to_stderr
- message3_nolog
- message1
- message1_nolog
- message_with_string
- ATTRIBUTE_FORMAT_PRINTF
- message
- update_echo_area
- ensure_echo_area_buffers
- with_echo_area_buffer
- with_echo_area_buffer_unwind_data
- unwind_with_echo_area_buffer
- setup_echo_area_for_printing
- display_echo_area
- display_echo_area_1
- resize_echo_area_exactly
- resize_mini_window_1
- resize_mini_window
- current_message
- current_message_1
- push_message
- restore_message
- pop_message_unwind
- check_message_stack
- clear_message_stack
- truncate_echo_area
- truncate_message_1
- set_message
- set_message_1
- clear_message
- clear_garbaged_frames
- echo_area_display
- window_buffer_changed
- mode_line_update_needed
- window_frozen_p
- format_mode_line_unwind_data
- unwind_format_mode_line
- store_mode_line_noprop_char
- store_mode_line_noprop
- gui_consider_frame_title
- needs_no_redisplay
- prepare_menu_bars
- update_menu_bar
- restore_selected_window
- restore_frame_selected_window
- update_tab_bar
- display_tab_bar
- build_desired_tab_bar_string
- display_tab_bar_line
- tab_bar_height
- redisplay_tab_bar
- tab_bar_item_info
- get_tab_bar_item
- handle_tab_bar_click
- note_tab_bar_highlight
- tty_get_tab_bar_item
- tty_handle_tab_bar_click
- update_tool_bar
- build_desired_tool_bar_string
- display_tool_bar_line
- tool_bar_height
- redisplay_tool_bar
- tool_bar_item_info
- get_tool_bar_item
- handle_tool_bar_click_with_device
- handle_tool_bar_click
- note_tool_bar_highlight
- hscroll_window_tree
- hscroll_windows
- debug_method_add
- text_outside_line_unchanged_p
- redisplay
- overlay_arrow_string_or_property
- overlay_arrow_in_current_buffer_p
- overlay_arrows_changed_p
- update_overlay_arrows
- overlay_arrow_at_row
- check_point_in_composition
- reconsider_clip_changes
- propagate_buffer_redisplay
- redisplay_internal
- unwind_redisplay_preserve_echo_area
- redisplay_preserve_echo_area
- unwind_redisplay
- unwind_display_working_on_window
- mark_window_display_accurate_1
- mark_window_display_accurate
- disp_char_vector
- block_buffer_flips
- unblock_buffer_flips
- buffer_flipping_blocked_p
- redisplay_windows
- redisplay_window_error
- redisplay_window_0
- redisplay_window_1
- update_redisplay_ticks
- set_cursor_from_row
- run_window_scroll_functions
- cursor_row_fully_visible_p
- try_scrolling
- compute_window_start_on_continuation_line
- try_cursor_movement
- set_vertical_scroll_bar
- set_horizontal_scroll_bar
- window_start_acceptable_p
- DEFUN
- redisplay_window
- try_window
- try_window_reusing_current_matrix
- find_last_row_displaying_text
- find_last_unchanged_at_beg_row
- find_first_unchanged_at_end_row
- sync_frame_with_window_matrix_rows
- row_containing_pos
- try_window_id
- dump_glyph_row
- dump_glyph
- dump_glyph_row
- DEFUN
- DEFUN
- DEFUN
- get_overlay_arrow_glyph_row
- insert_left_trunc_glyphs
- row_hash
- compute_line_metrics
- clear_position
- append_space_for_newline
- extend_face_to_end_of_line
- trailing_whitespace_p
- highlight_trailing_whitespace
- row_for_charpos_p
- cursor_row_p
- push_prefix_prop
- get_it_property
- get_line_prefix_it_property
- handle_line_prefix
- unproduce_glyphs
- find_row_edges
- display_count_lines_logically
- display_count_lines_visually
- maybe_produce_line_number
- should_produce_line_number
- row_text_area_empty
- display_line
- DEFUN
- DEFUN
- DEFUN
- display_menu_bar
- deep_copy_glyph_row
- display_tty_menu_item
- redisplay_mode_lines
- display_mode_lines
- display_mode_line
- move_elt_to_front
- safe_set_text_properties
- display_mode_element
- store_mode_line_string
- pint2str
- pint2hrstr
- decode_mode_spec_coding
- percent99
- decode_mode_spec
- count_lines
- display_count_lines
- display_string
- invisible_prop
- DEFUN
- calc_pixel_width_or_height
- get_font_ascent_descent
- dump_glyph_string
- init_glyph_string
- append_glyph_string_lists
- prepend_glyph_string_lists
- append_glyph_string
- get_char_face_and_encoding
- get_glyph_face_and_encoding
- get_char_glyph_code
- fill_composite_glyph_string
- fill_gstring_glyph_string
- fill_glyphless_glyph_string
- fill_glyph_string
- fill_image_glyph_string
- fill_xwidget_glyph_string
- fill_stretch_glyph_string
- get_per_char_metric
- normal_char_ascent_descent
- normal_char_height
- gui_get_glyph_overhangs
- left_overwritten
- left_overwriting
- right_overwritten
- right_overwriting
- set_glyph_string_background_width
- glyph_string_containing_background_width
- compute_overhangs_and_x
- draw_glyphs
- font_for_underline_metrics
- append_glyph
- append_composite_glyph
- take_vertical_position_into_account
- produce_image_glyph
- produce_xwidget_glyph
- append_stretch_glyph
- produce_stretch_glyph
- produce_special_glyphs
- calc_line_height_property
- append_glyphless_glyph
- produce_glyphless_glyph
- gui_produce_glyphs
- gui_write_glyphs
- gui_insert_glyphs
- gui_clear_end_of_line
- get_specified_cursor_type
- set_frame_cursor_types
- get_window_cursor_type
- notice_overwritten_cursor
- gui_fix_overlapping_area
- draw_phys_cursor_glyph
- erase_phys_cursor
- display_and_set_cursor
- update_window_cursor
- update_cursor_in_window_tree
- gui_update_cursor
- gui_clear_cursor
- draw_row_with_mouse_face
- show_mouse_face
- clear_mouse_face
- coords_in_mouse_face_p
- cursor_in_mouse_face_p
- rows_from_pos_range
- mouse_face_from_buffer_pos
- fast_find_string_pos
- mouse_face_from_string_pos
- on_hot_spot_p
- find_hot_spot
- define_frame_cursor1
- note_mode_line_or_margin_highlight
- note_mouse_highlight
- gui_clear_window_mouse_face
- cancel_mouse_face
- expose_area
- expose_line
- expose_overlaps
- phys_cursor_in_rect_p
- gui_draw_vertical_border
- gui_draw_right_divider
- gui_draw_bottom_divider
- expose_window
- expose_window_tree
- expose_frame
- gui_intersect_rectangles
- syms_of_xdisp
- init_xdisp
- show_hourglass
- start_hourglass
- cancel_hourglass
- adjust_glyph_width_for_mouse_face
- get_cursor_offset_for_mouse_face
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435 #include <config.h>
436 #include <stdlib.h>
437 #include <limits.h>
438 #include <math.h>
439
440 #include "lisp.h"
441 #include "atimer.h"
442 #include "composite.h"
443 #include "keyboard.h"
444 #include "sysstdio.h"
445 #include "systime.h"
446 #include "frame.h"
447 #include "window.h"
448 #include "termchar.h"
449 #include "dispextern.h"
450 #include "character.h"
451 #include "category.h"
452 #include "buffer.h"
453 #include "charset.h"
454 #include "indent.h"
455 #include "commands.h"
456 #include "keymap.h"
457 #include "disptab.h"
458 #include "termhooks.h"
459 #include "termopts.h"
460 #include "intervals.h"
461 #include "coding.h"
462 #include "region-cache.h"
463 #include "font.h"
464 #include "fontset.h"
465 #include "blockinput.h"
466 #include "xwidget.h"
467 #ifdef HAVE_WINDOW_SYSTEM
468 #include TERM_HEADER
469 #endif
470
471 #ifndef FRAME_OUTPUT_DATA
472 #define FRAME_OUTPUT_DATA(f) (NULL)
473 #endif
474
475 #define DISP_INFINITY 10000000
476
477
478 static Lisp_Object list_of_error;
479
480 #ifdef HAVE_WINDOW_SYSTEM
481
482
483
484
485 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(IT) \
486 (!NILP (Voverflow_newline_into_fringe) \
487 && FRAME_WINDOW_P ((IT)->f) \
488 && ((IT)->bidi_it.paragraph_dir == R2L \
489 ? (WINDOW_LEFT_FRINGE_WIDTH ((IT)->w) > 0) \
490 : (WINDOW_RIGHT_FRINGE_WIDTH ((IT)->w) > 0)) \
491 && (IT)->current_x == (IT)->last_visible_x)
492
493 #else
494 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) false
495 #endif
496
497
498
499
500
501 #define IT_DISPLAYING_WHITESPACE(it) \
502 ((it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t')) \
503 || ((STRINGP (it->string) \
504 && (SREF (it->string, IT_STRING_BYTEPOS (*it)) == ' ' \
505 || SREF (it->string, IT_STRING_BYTEPOS (*it)) == '\t')) \
506 || (it->s \
507 && (it->s[IT_BYTEPOS (*it)] == ' ' \
508 || it->s[IT_BYTEPOS (*it)] == '\t')) \
509 || (IT_BYTEPOS (*it) < ZV_BYTE \
510 && (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \
511 || *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t'))))
512
513
514
515 #define NOT_AT_EOL '<'
516 #define NOT_AT_BOL '>'
517 #define LINE_BREAKABLE '|'
518
519 static bool
520 it_char_has_category(struct it *it, int cat)
521 {
522 int ch = 0;
523 if (it->what == IT_CHARACTER)
524 ch = it->c;
525 else if (STRINGP (it->string))
526 ch = SREF (it->string, IT_STRING_BYTEPOS (*it));
527 else if (it->s)
528 ch = it->s[IT_BYTEPOS (*it)];
529 else if (IT_BYTEPOS (*it) < ZV_BYTE)
530 ch = *BYTE_POS_ADDR (IT_BYTEPOS (*it));
531
532 if (ch == 0)
533 return false;
534 else
535 return CHAR_HAS_CATEGORY (ch, cat);
536 }
537
538
539 static bool
540 char_can_wrap_before (struct it *it)
541 {
542 if (!word_wrap_by_category)
543 return !IT_DISPLAYING_WHITESPACE (it);
544
545
546
547
548 int not_at_bol;
549 if (it->glyph_row && it->glyph_row->reversed_p)
550 not_at_bol = NOT_AT_EOL;
551 else
552 not_at_bol = NOT_AT_BOL;
553
554
555 return (!IT_DISPLAYING_WHITESPACE (it)
556
557 && !it_char_has_category (it, not_at_bol));
558 }
559
560
561 static bool
562 char_can_wrap_after (struct it *it)
563 {
564 if (!word_wrap_by_category)
565 return IT_DISPLAYING_WHITESPACE (it);
566
567
568
569
570 int not_at_eol;
571 if (it->glyph_row && it->glyph_row->reversed_p)
572 not_at_eol = NOT_AT_BOL;
573 else
574 not_at_eol = NOT_AT_EOL;
575
576 return (IT_DISPLAYING_WHITESPACE (it)
577
578 || (it_char_has_category (it, LINE_BREAKABLE)
579 && !it_char_has_category (it, not_at_eol)));
580 }
581
582 #undef IT_DISPLAYING_WHITESPACE
583 #undef NOT_AT_EOL
584 #undef NOT_AT_BOL
585 #undef LINE_BREAKABLE
586
587
588
589
590 static int
591 fill_column_indicator_column (struct it *it, int char_width)
592 {
593 if (display_fill_column_indicator
594 && !it->w->pseudo_window_p
595 && it->continuation_lines_width == 0
596 && CHARACTERP (Vdisplay_fill_column_indicator_character))
597 {
598 Lisp_Object col = (EQ (Vdisplay_fill_column_indicator_column, Qt)
599 ? BVAR (current_buffer, fill_column)
600 : Vdisplay_fill_column_indicator_column);
601
602
603
604 if (RANGED_FIXNUMP (0, col, INT_MAX))
605 {
606 int icol = XFIXNUM (col);
607 if (!INT_MULTIPLY_WRAPV (char_width, icol, &icol)
608 && !INT_ADD_WRAPV (it->lnum_pixel_width, icol, &icol))
609 return icol;
610 }
611 }
612 return -1;
613 }
614
615
616
617 bool noninteractive_need_newline;
618
619
620
621 static bool message_log_need_newline;
622
623
624
625
626 static Lisp_Object message_dolog_marker1;
627 static Lisp_Object message_dolog_marker2;
628 static Lisp_Object message_dolog_marker3;
629
630
631
632
633
634
635 static struct text_pos this_line_start_pos;
636
637
638
639
640 static struct text_pos this_line_end_pos;
641
642
643
644 static int this_line_vpos;
645 static int this_line_y;
646 static int this_line_pixel_height;
647
648
649
650
651 static int this_line_start_x;
652
653
654
655
656
657 static struct text_pos this_line_min_pos;
658
659
660
661 static struct buffer *this_line_buffer;
662
663
664
665 static bool overlay_arrow_seen;
666
667
668
669 static Lisp_Object default_invis_vector[3];
670
671
672
673
674
675 Lisp_Object echo_area_window;
676
677
678
679
680 static Lisp_Object Vmessage_stack;
681
682
683
684
685 static bool message_enable_multibyte;
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717 int windows_or_buffers_changed;
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738 int update_mode_lines;
739
740
741
742
743 static bool line_number_displayed;
744
745
746
747
748 Lisp_Object echo_area_buffer[2];
749
750
751
752 static Lisp_Object echo_buffer[2];
753
754
755
756 static Lisp_Object Vwith_echo_area_save_vector;
757
758
759
760
761 static bool display_last_displayed_message_p;
762
763
764
765
766 static bool message_buf_print;
767
768
769
770
771 static bool message_cleared_p;
772
773
774
775
776 #define MAX_SCRATCH_GLYPHS 100
777 static struct glyph_row scratch_glyph_row;
778 static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
779
780
781
782 static int last_height;
783
784
785
786 bool help_echo_showing_p;
787
788
789
790
791
792
793
794 #define TEXT_PROP_DISTANCE_LIMIT 100
795
796
797
798
799
800
801
802
803 #define SAVE_IT(ITCOPY, ITORIG, CACHE) \
804 do { \
805 if (CACHE) \
806 bidi_unshelve_cache (CACHE, true); \
807 ITCOPY = ITORIG; \
808 CACHE = bidi_shelve_cache (); \
809 } while (false)
810
811 #define RESTORE_IT(pITORIG, pITCOPY, CACHE) \
812 do { \
813 if (pITORIG != pITCOPY) \
814 *(pITORIG) = *(pITCOPY); \
815 bidi_unshelve_cache (CACHE, false); \
816 CACHE = NULL; \
817 } while (false)
818
819
820 enum { REDISPLAY_SOME = 2};
821
822 static bool calc_pixel_width_or_height (double *, struct it *, Lisp_Object,
823 struct font *, bool, int *);
824
825 void
826 redisplay_other_windows (void)
827 {
828 if (!windows_or_buffers_changed)
829 windows_or_buffers_changed = REDISPLAY_SOME;
830 }
831
832 void
833 wset_redisplay (struct window *w)
834 {
835
836 if (!BASE_EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window))
837 redisplay_other_windows ();
838 w->redisplay = true;
839 }
840
841 void
842 fset_redisplay (struct frame *f)
843 {
844 redisplay_other_windows ();
845 f->redisplay = true;
846 }
847
848 void
849 bset_redisplay (struct buffer *b)
850 {
851 int count = buffer_window_count (b);
852 if (count > 0)
853 {
854
855 if (count > 1 || b != XBUFFER (XWINDOW (selected_window)->contents))
856 redisplay_other_windows ();
857
858
859
860 b->text->redisplay = true;
861 }
862 }
863
864 void
865 bset_update_mode_line (struct buffer *b)
866 {
867 if (!update_mode_lines)
868 update_mode_lines = REDISPLAY_SOME;
869 b->text->redisplay = true;
870 }
871
872 void
873 wset_update_mode_line (struct window *w)
874 {
875 w->update_mode_line = true;
876
877
878
879
880
881
882 wset_redisplay (w);
883 }
884
885 DEFUN ("set-buffer-redisplay", Fset_buffer_redisplay,
886 Sset_buffer_redisplay, 4, 4, 0,
887 doc:
888 )
889 (Lisp_Object symbol, Lisp_Object newval, Lisp_Object op, Lisp_Object where)
890 {
891 bset_update_mode_line (current_buffer);
892 current_buffer->prevent_redisplay_optimizations_p = true;
893 return Qnil;
894 }
895
896
897
898
899
900 #ifdef GLYPH_DEBUG
901 extern bool trace_redisplay_p EXTERNALLY_VISIBLE;
902 bool trace_redisplay_p;
903 #else
904 enum { trace_redisplay_p = false };
905 #endif
906 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
907 redisplay_trace (char const *fmt, ...)
908 {
909 if (trace_redisplay_p)
910 {
911 va_list ap;
912 va_start (ap, fmt);
913 vprintf (fmt, ap);
914 va_end (ap);
915 }
916 }
917
918 #ifdef DEBUG_TRACE_MOVE
919 extern bool trace_move EXTERNALLY_VISIBLE;
920 bool trace_move;
921 #else
922 enum { trace_move = false };
923 #endif
924 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
925 move_trace (char const *fmt, ...)
926 {
927 if (trace_move)
928 {
929 va_list ap;
930 va_start (ap, fmt);
931 vprintf (fmt, ap);
932 va_end (ap);
933 }
934 }
935
936
937
938 static struct buffer *displayed_buffer;
939
940
941
942 enum prop_handled
943 {
944 HANDLED_NORMALLY,
945 HANDLED_RECOMPUTE_PROPS,
946 HANDLED_OVERLAY_STRING_CONSUMED,
947 HANDLED_RETURN
948 };
949
950
951
952
953 struct props
954 {
955
956 short name;
957
958
959 enum prop_idx idx;
960
961
962
963 enum prop_handled (*handler) (struct it *it);
964 };
965
966 static enum prop_handled handle_face_prop (struct it *);
967 static enum prop_handled handle_invisible_prop (struct it *);
968 static enum prop_handled handle_display_prop (struct it *);
969 static enum prop_handled handle_composition_prop (struct it *);
970 static enum prop_handled handle_overlay_change (struct it *);
971 static enum prop_handled handle_fontified_prop (struct it *);
972
973
974
975 static struct props it_props[] =
976 {
977 {SYMBOL_INDEX (Qfontified), FONTIFIED_PROP_IDX, handle_fontified_prop},
978
979
980 {SYMBOL_INDEX (Qface), FACE_PROP_IDX, handle_face_prop},
981 {SYMBOL_INDEX (Qdisplay), DISPLAY_PROP_IDX, handle_display_prop},
982 {SYMBOL_INDEX (Qinvisible), INVISIBLE_PROP_IDX, handle_invisible_prop},
983 {SYMBOL_INDEX (Qcomposition), COMPOSITION_PROP_IDX, handle_composition_prop},
984 {0, 0, NULL}
985 };
986
987
988
989 enum move_it_result
990 {
991
992 MOVE_UNDEFINED,
993
994
995 MOVE_POS_MATCH_OR_ZV,
996
997
998 MOVE_X_REACHED,
999
1000
1001
1002 MOVE_LINE_CONTINUED,
1003
1004
1005
1006 MOVE_LINE_TRUNCATED,
1007
1008
1009 MOVE_NEWLINE_OR_CR
1010 };
1011
1012
1013
1014
1015
1016
1017 #define CLEAR_FACE_CACHE_COUNT 500
1018 static int clear_face_cache_count;
1019
1020
1021
1022 #ifdef HAVE_WINDOW_SYSTEM
1023 #define CLEAR_IMAGE_CACHE_COUNT 101
1024 static int clear_image_cache_count;
1025
1026
1027 static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
1028 #endif
1029
1030
1031
1032 bool redisplaying_p;
1033
1034
1035
1036
1037
1038
1039
1040
1041 bool display_working_on_window_p;
1042
1043
1044
1045
1046 Lisp_Object help_echo_string;
1047 Lisp_Object help_echo_window;
1048 Lisp_Object help_echo_object;
1049 ptrdiff_t help_echo_pos;
1050
1051
1052
1053 Lisp_Object previous_help_echo_string;
1054
1055
1056
1057 #ifdef HAVE_WINDOW_SYSTEM
1058
1059
1060 static bool hourglass_shown_p;
1061
1062
1063
1064 static struct atimer *hourglass_atimer;
1065
1066 #endif
1067
1068
1069
1070 #define DEFAULT_HOURGLASS_DELAY 1
1071
1072 #ifdef HAVE_WINDOW_SYSTEM
1073
1074
1075 #define THIN_SPACE_WIDTH 1
1076
1077 #endif
1078
1079
1080
1081 static void setup_for_ellipsis (struct it *, int);
1082 static void set_iterator_to_next (struct it *, bool);
1083 static void mark_window_display_accurate_1 (struct window *, bool);
1084 static bool row_for_charpos_p (struct glyph_row *, ptrdiff_t);
1085 static bool cursor_row_p (struct glyph_row *);
1086 static int redisplay_mode_lines (Lisp_Object, bool);
1087
1088 static void handle_line_prefix (struct it *);
1089
1090 static void handle_stop_backwards (struct it *, ptrdiff_t);
1091 static void unwind_with_echo_area_buffer (Lisp_Object);
1092 static Lisp_Object with_echo_area_buffer_unwind_data (struct window *);
1093 static bool current_message_1 (void *, Lisp_Object);
1094 static bool truncate_message_1 (void *, Lisp_Object);
1095 static void set_message (Lisp_Object);
1096 static bool set_message_1 (void *, Lisp_Object);
1097 static bool display_echo_area_1 (void *, Lisp_Object);
1098 static bool resize_mini_window_1 (void *, Lisp_Object);
1099 static void unwind_redisplay (void);
1100 static void extend_face_to_end_of_line (struct it *);
1101 static intmax_t message_log_check_duplicate (ptrdiff_t, ptrdiff_t);
1102 static void push_it (struct it *, struct text_pos *);
1103 static void iterate_out_of_display_property (struct it *);
1104 static void pop_it (struct it *);
1105 static void redisplay_internal (void);
1106 static void echo_area_display (bool);
1107 static void block_buffer_flips (void);
1108 static void unblock_buffer_flips (void);
1109 static void redisplay_windows (Lisp_Object);
1110 static void redisplay_window (Lisp_Object, bool);
1111 static Lisp_Object redisplay_window_error (Lisp_Object);
1112 static Lisp_Object redisplay_window_0 (Lisp_Object);
1113 static Lisp_Object redisplay_window_1 (Lisp_Object);
1114 static bool set_cursor_from_row (struct window *, struct glyph_row *,
1115 struct glyph_matrix *, ptrdiff_t, ptrdiff_t,
1116 int, int);
1117 static bool cursor_row_fully_visible_p (struct window *, bool, bool, bool);
1118 static bool update_menu_bar (struct frame *, bool, bool);
1119 static bool try_window_reusing_current_matrix (struct window *);
1120 static int try_window_id (struct window *);
1121 static void maybe_produce_line_number (struct it *);
1122 static bool should_produce_line_number (struct it *);
1123 static bool display_line (struct it *, int);
1124 static int display_mode_lines (struct window *);
1125 static int display_mode_line (struct window *, enum face_id, Lisp_Object);
1126 static int display_mode_element (struct it *, int, int, int, Lisp_Object,
1127 Lisp_Object, bool);
1128 static int store_mode_line_string (const char *, Lisp_Object, bool, int, int,
1129 Lisp_Object);
1130 static const char *decode_mode_spec (struct window *, int, int, Lisp_Object *);
1131 static void display_menu_bar (struct window *);
1132 static void display_tab_bar (struct window *);
1133 static void update_tab_bar (struct frame *, bool);
1134 static ptrdiff_t display_count_lines (ptrdiff_t, ptrdiff_t, ptrdiff_t,
1135 ptrdiff_t *);
1136 static void pint2str (register char *, register int, register ptrdiff_t);
1137
1138 static int display_string (const char *, Lisp_Object, Lisp_Object,
1139 ptrdiff_t, ptrdiff_t, struct it *, int, int, int,
1140 int);
1141 static void compute_line_metrics (struct it *);
1142 static bool get_overlay_strings (struct it *, ptrdiff_t);
1143 static bool get_overlay_strings_1 (struct it *, ptrdiff_t, bool);
1144 static void next_overlay_string (struct it *);
1145 static void reseat (struct it *, struct text_pos, bool);
1146 static void reseat_1 (struct it *, struct text_pos, bool);
1147 static bool next_element_from_display_vector (struct it *);
1148 static bool next_element_from_string (struct it *);
1149 static bool next_element_from_c_string (struct it *);
1150 static bool next_element_from_buffer (struct it *);
1151 static bool next_element_from_composition (struct it *);
1152 static bool next_element_from_image (struct it *);
1153 static bool next_element_from_stretch (struct it *);
1154 static bool next_element_from_xwidget (struct it *);
1155 static void load_overlay_strings (struct it *, ptrdiff_t);
1156 static bool get_next_display_element (struct it *);
1157 static enum move_it_result
1158 move_it_in_display_line_to (struct it *, ptrdiff_t, int,
1159 enum move_operation_enum);
1160 static void get_visually_first_element (struct it *);
1161 static void compute_stop_pos (struct it *);
1162 static int face_before_or_after_it_pos (struct it *, bool);
1163 static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object,
1164 Lisp_Object, struct text_pos *, ptrdiff_t, bool);
1165 static int handle_single_display_spec (struct it *, Lisp_Object, Lisp_Object,
1166 Lisp_Object, struct text_pos *,
1167 ptrdiff_t, int, bool, bool);
1168 static int underlying_face_id (const struct it *);
1169
1170 #define face_before_it_pos(IT) face_before_or_after_it_pos (IT, true)
1171 #define face_after_it_pos(IT) face_before_or_after_it_pos (IT, false)
1172
1173 #ifdef HAVE_WINDOW_SYSTEM
1174
1175 static void update_tool_bar (struct frame *, bool);
1176 static void gui_draw_bottom_divider (struct window *w);
1177 static void notice_overwritten_cursor (struct window *,
1178 enum glyph_row_area,
1179 int, int, int, int);
1180 static int normal_char_height (struct font *, int);
1181 static void normal_char_ascent_descent (struct font *, int, int *, int *);
1182
1183 static void append_stretch_glyph (struct it *, Lisp_Object,
1184 int, int, int);
1185
1186 static Lisp_Object get_it_property (struct it *, Lisp_Object);
1187 static Lisp_Object calc_line_height_property (struct it *, Lisp_Object,
1188 struct font *, int, bool);
1189 static int adjust_glyph_width_for_mouse_face (struct glyph *,
1190 struct glyph_row *,
1191 struct window *, struct face *,
1192 struct face *);
1193 static void get_cursor_offset_for_mouse_face (struct window *w,
1194 struct glyph_row *row,
1195 int *offset);
1196 #endif
1197
1198 static void produce_special_glyphs (struct it *, enum display_element_type);
1199 static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
1200 static bool coords_in_mouse_face_p (struct window *, int, int);
1201 static void reset_box_start_end_flags (struct it *);
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215 int
1216 window_text_bottom_y (struct window *w)
1217 {
1218 int height = WINDOW_PIXEL_HEIGHT (w);
1219
1220 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1221
1222 if (window_wants_mode_line (w))
1223 height -= CURRENT_MODE_LINE_HEIGHT (w);
1224
1225 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1226
1227 return height;
1228 }
1229
1230
1231
1232
1233
1234 int
1235 window_box_width (struct window *w, enum glyph_row_area area)
1236 {
1237 int width = w->pixel_width;
1238
1239 if (!w->pseudo_window_p)
1240 {
1241 width -= WINDOW_SCROLL_BAR_AREA_WIDTH (w);
1242 width -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
1243
1244 if (area == TEXT_AREA)
1245 width -= (WINDOW_MARGINS_WIDTH (w)
1246 + WINDOW_FRINGES_WIDTH (w));
1247 else if (area == LEFT_MARGIN_AREA)
1248 width = WINDOW_LEFT_MARGIN_WIDTH (w);
1249 else if (area == RIGHT_MARGIN_AREA)
1250 width = WINDOW_RIGHT_MARGIN_WIDTH (w);
1251 }
1252
1253
1254
1255 return max (0, width);
1256 }
1257
1258
1259
1260
1261
1262 int
1263 window_box_height (struct window *w)
1264 {
1265 struct frame *f = XFRAME (w->frame);
1266 int height = WINDOW_PIXEL_HEIGHT (w);
1267
1268 eassert (height >= 0);
1269
1270 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1271 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1272
1273
1274
1275
1276
1277
1278
1279 if (window_wants_mode_line (w))
1280 {
1281 if (w->mode_line_height >= 0)
1282 height -= w->mode_line_height;
1283 else
1284 {
1285 struct glyph_row *ml_row
1286 = (w->current_matrix && w->current_matrix->rows
1287 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
1288 : 0);
1289 if (ml_row && ml_row->mode_line_p)
1290 height -= ml_row->height;
1291 else
1292 height -= estimate_mode_line_height
1293 (f, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w));
1294 }
1295 }
1296
1297 if (window_wants_tab_line (w))
1298 {
1299 if (w->tab_line_height >= 0)
1300 height -= w->tab_line_height;
1301 else
1302 {
1303 struct glyph_row *tl_row
1304 = (w->current_matrix && w->current_matrix->rows
1305 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
1306 : 0);
1307 if (tl_row && tl_row->mode_line_p)
1308 height -= tl_row->height;
1309 else
1310 height -= estimate_mode_line_height (f, TAB_LINE_FACE_ID);
1311 }
1312 }
1313
1314 if (window_wants_header_line (w))
1315 {
1316 if (w->header_line_height >= 0)
1317 height -= w->header_line_height;
1318 else
1319 {
1320 struct glyph_row *hl_row
1321 = (w->current_matrix && w->current_matrix->rows
1322 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
1323 : 0);
1324 if (hl_row && hl_row->mode_line_p)
1325 height -= hl_row->height;
1326 else
1327 height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
1328 }
1329 }
1330
1331
1332
1333 return max (0, height);
1334 }
1335
1336
1337
1338
1339
1340 int
1341 window_box_left_offset (struct window *w, enum glyph_row_area area)
1342 {
1343 int x;
1344
1345 if (w->pseudo_window_p)
1346 return 0;
1347
1348 x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
1349
1350 if (area == TEXT_AREA)
1351 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1352 + window_box_width (w, LEFT_MARGIN_AREA));
1353 else if (area == RIGHT_MARGIN_AREA)
1354 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1355 + window_box_width (w, LEFT_MARGIN_AREA)
1356 + window_box_width (w, TEXT_AREA)
1357 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1358 ? 0
1359 : WINDOW_RIGHT_FRINGE_WIDTH (w)));
1360 else if (area == LEFT_MARGIN_AREA
1361 && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1362 x += WINDOW_LEFT_FRINGE_WIDTH (w);
1363
1364
1365 return min (x, w->pixel_width);
1366 }
1367
1368
1369
1370
1371
1372
1373 static int
1374 window_box_right_offset (struct window *w, enum glyph_row_area area)
1375 {
1376
1377 return min (window_box_left_offset (w, area) + window_box_width (w, area),
1378 w->pixel_width);
1379 }
1380
1381
1382
1383
1384
1385 int
1386 window_box_left (struct window *w, enum glyph_row_area area)
1387 {
1388 struct frame *f = XFRAME (w->frame);
1389 int x;
1390
1391 if (w->pseudo_window_p)
1392 return FRAME_INTERNAL_BORDER_WIDTH (f);
1393
1394 x = (WINDOW_LEFT_EDGE_X (w)
1395 + window_box_left_offset (w, area));
1396
1397 return x;
1398 }
1399
1400
1401
1402
1403
1404
1405 int
1406 window_box_right (struct window *w, enum glyph_row_area area)
1407 {
1408 return window_box_left (w, area) + window_box_width (w, area);
1409 }
1410
1411
1412
1413
1414
1415
1416
1417
1418 void
1419 window_box (struct window *w, enum glyph_row_area area, int *box_x,
1420 int *box_y, int *box_width, int *box_height)
1421 {
1422 if (box_width)
1423 *box_width = window_box_width (w, area);
1424 if (box_height)
1425 *box_height = window_box_height (w);
1426 if (box_x)
1427 *box_x = window_box_left (w, area);
1428 if (box_y)
1429 {
1430 *box_y = WINDOW_TOP_EDGE_Y (w);
1431 if (window_wants_tab_line (w))
1432 *box_y += CURRENT_TAB_LINE_HEIGHT (w);
1433 if (window_wants_header_line (w))
1434 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
1435 }
1436 }
1437
1438 #ifdef HAVE_WINDOW_SYSTEM
1439
1440
1441
1442
1443
1444
1445
1446
1447 static void
1448 window_box_edges (struct window *w, int *top_left_x, int *top_left_y,
1449 int *bottom_right_x, int *bottom_right_y)
1450 {
1451 window_box (w, ANY_AREA, top_left_x, top_left_y,
1452 bottom_right_x, bottom_right_y);
1453 *bottom_right_x += *top_left_x;
1454 *bottom_right_y += *top_left_y;
1455 }
1456
1457 #endif
1458
1459
1460
1461
1462
1463
1464
1465
1466 int
1467 line_bottom_y (struct it *it)
1468 {
1469 int line_height = it->max_ascent + it->max_descent;
1470 int line_top_y = it->current_y;
1471
1472 if (line_height == 0)
1473 {
1474 if (last_height)
1475 line_height = last_height;
1476 else if (IT_CHARPOS (*it) < ZV)
1477 {
1478 move_it_by_lines (it, 1);
1479 line_height = (it->max_ascent || it->max_descent
1480 ? it->max_ascent + it->max_descent
1481 : last_height);
1482 }
1483 else
1484 {
1485 struct glyph_row *row = it->glyph_row;
1486
1487
1488 it->glyph_row = NULL;
1489 it->what = IT_CHARACTER;
1490 it->c = ' ';
1491 it->len = 1;
1492 PRODUCE_GLYPHS (it);
1493 line_height = it->ascent + it->descent;
1494 it->glyph_row = row;
1495 }
1496 }
1497
1498 return line_top_y + line_height;
1499 }
1500
1501 DEFUN ("line-pixel-height", Fline_pixel_height,
1502 Sline_pixel_height, 0, 0, 0,
1503 doc:
1504
1505 )
1506 (void)
1507 {
1508 struct it it;
1509 struct text_pos pt;
1510 struct window *w = XWINDOW (selected_window);
1511 struct buffer *old_buffer = NULL;
1512 Lisp_Object result;
1513
1514 if (XBUFFER (w->contents) != current_buffer)
1515 {
1516 old_buffer = current_buffer;
1517 set_buffer_internal_1 (XBUFFER (w->contents));
1518 }
1519 SET_TEXT_POS (pt, PT, PT_BYTE);
1520 void *itdata = bidi_shelve_cache ();
1521 start_display (&it, w, pt);
1522
1523
1524
1525 move_it_by_lines (&it, 0);
1526 it.vpos = it.current_y = 0;
1527 last_height = 0;
1528 result = make_fixnum (line_bottom_y (&it));
1529 if (old_buffer)
1530 set_buffer_internal_1 (old_buffer);
1531
1532 bidi_unshelve_cache (itdata, false);
1533 return result;
1534 }
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550 int
1551 default_line_pixel_height (struct window *w)
1552 {
1553 struct frame *f = WINDOW_XFRAME (w);
1554 int height = FRAME_LINE_HEIGHT (f);
1555
1556 if (!FRAME_INITIAL_P (f) && BUFFERP (w->contents))
1557 {
1558 struct buffer *b = XBUFFER (w->contents);
1559 Lisp_Object val = BVAR (b, extra_line_spacing);
1560
1561 if (NILP (val))
1562 val = BVAR (&buffer_defaults, extra_line_spacing);
1563 if (!NILP (val))
1564 {
1565 if (RANGED_FIXNUMP (0, val, INT_MAX))
1566 height += XFIXNAT (val);
1567 else if (FLOATP (val))
1568 {
1569 int addon = XFLOAT_DATA (val) * height + 0.5;
1570
1571 if (addon >= 0)
1572 height += addon;
1573 }
1574 }
1575 else
1576 height += f->extra_line_spacing;
1577 }
1578
1579 return height;
1580 }
1581
1582
1583
1584 static Lisp_Object
1585 string_from_display_spec (Lisp_Object spec)
1586 {
1587 if (VECTORP (spec))
1588 {
1589 for (ptrdiff_t i = 0; i < ASIZE (spec); i++)
1590 if (STRINGP (AREF (spec, i)))
1591 return AREF (spec, i);
1592 }
1593 else
1594 {
1595 for (; CONSP (spec); spec = XCDR (spec))
1596 if (STRINGP (XCAR (spec)))
1597 return XCAR (spec);
1598 }
1599 return spec;
1600 }
1601
1602
1603
1604
1605
1606 static int
1607 window_hscroll_limited (struct window *w, struct frame *f)
1608 {
1609 ptrdiff_t window_hscroll = w->hscroll;
1610 int window_text_width = window_box_width (w, TEXT_AREA);
1611 int colwidth = FRAME_COLUMN_WIDTH (f);
1612
1613 if (window_hscroll > (INT_MAX - window_text_width) / colwidth - 1)
1614 window_hscroll = (INT_MAX - window_text_width) / colwidth - 1;
1615
1616 return window_hscroll;
1617 }
1618
1619
1620
1621
1622
1623 static void
1624 reset_box_start_end_flags (struct it *it)
1625 {
1626
1627
1628 if (it->area == TEXT_AREA
1629
1630 && !(it->what == IT_IMAGE && it->image_id < 0))
1631 {
1632
1633
1634
1635
1636 if (it->face_box_p)
1637 it->start_of_box_run_p = false;
1638 it->end_of_box_run_p = false;
1639 }
1640 }
1641
1642
1643
1644
1645
1646
1647
1648 bool
1649 pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1650 int *rtop, int *rbot, int *rowh, int *vpos)
1651 {
1652 struct it it;
1653 void *itdata = bidi_shelve_cache ();
1654 struct text_pos top;
1655 bool visible_p = false;
1656 struct buffer *old_buffer = NULL;
1657 bool r2l = false;
1658
1659 if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
1660 return visible_p;
1661
1662 if (XBUFFER (w->contents) != current_buffer)
1663 {
1664 old_buffer = current_buffer;
1665 set_buffer_internal_1 (XBUFFER (w->contents));
1666 }
1667
1668 SET_TEXT_POS_FROM_MARKER (top, w->start);
1669
1670
1671
1672
1673 if (CHARPOS (top) > ZV || CHARPOS (top) < BEGV)
1674 SET_TEXT_POS (top, BEGV, BEGV_BYTE);
1675
1676
1677
1678 if (charpos >= 0 && CHARPOS (top) > charpos)
1679 return visible_p;
1680
1681
1682
1683
1684
1685
1686
1687
1688 int prev_mode_line_height = w->mode_line_height;
1689 int prev_header_line_height = w->header_line_height;
1690 int prev_tab_line_height = w->tab_line_height;
1691
1692 if (window_wants_mode_line (w))
1693 {
1694 Lisp_Object window_mode_line_format
1695 = window_parameter (w, Qmode_line_format);
1696
1697 w->mode_line_height
1698 = display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
1699 NILP (window_mode_line_format)
1700 ? BVAR (current_buffer, mode_line_format)
1701 : window_mode_line_format);
1702 }
1703
1704 if (window_wants_tab_line (w))
1705 {
1706 Lisp_Object window_tab_line_format
1707 = window_parameter (w, Qtab_line_format);
1708
1709 w->tab_line_height
1710 = display_mode_line (w, TAB_LINE_FACE_ID,
1711 NILP (window_tab_line_format)
1712 ? BVAR (current_buffer, tab_line_format)
1713 : window_tab_line_format);
1714 }
1715
1716 if (window_wants_header_line (w))
1717 {
1718 Lisp_Object window_header_line_format
1719 = window_parameter (w, Qheader_line_format);
1720
1721 w->header_line_height
1722 = display_mode_line (w, HEADER_LINE_FACE_ID,
1723 NILP (window_header_line_format)
1724 ? BVAR (current_buffer, header_line_format)
1725 : window_header_line_format);
1726 }
1727
1728 start_display (&it, w, top);
1729 move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
1730 (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
1731
1732
1733
1734 if (!NILP (Vdisplay_line_numbers)
1735 && it.current_x >= it.first_visible_x
1736 && IT_CHARPOS (it) == charpos
1737 && !it.line_number_produced_p)
1738 {
1739
1740
1741
1742 if (!it.lnum_pixel_width)
1743 {
1744 struct it it2;
1745 void *it2data = NULL;
1746
1747 SAVE_IT (it2, it, it2data);
1748 move_it_by_lines (&it, 1);
1749 it2.lnum_pixel_width = it.lnum_pixel_width;
1750 RESTORE_IT (&it, &it2, it2data);
1751 }
1752 it.current_x += it.lnum_pixel_width;
1753 }
1754
1755 if (charpos >= 0
1756 && (((!it.bidi_p || it.bidi_it.scan_dir != -1)
1757 && IT_CHARPOS (it) >= charpos)
1758
1759
1760
1761 || (it.bidi_p && it.bidi_it.scan_dir == -1
1762 && IT_CHARPOS (it) <= charpos)))
1763 {
1764
1765
1766
1767
1768
1769
1770 int top_x = it.current_x;
1771 int top_y = it.current_y;
1772 int window_top_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
1773 int bottom_y;
1774 struct it save_it;
1775 void *save_it_data = NULL;
1776
1777
1778 SAVE_IT (save_it, it, save_it_data);
1779 last_height = 0;
1780 bottom_y = line_bottom_y (&it);
1781 if (top_y < window_top_y)
1782 visible_p = bottom_y > window_top_y;
1783 else if (top_y < it.last_visible_y)
1784 visible_p = true;
1785 if (bottom_y >= it.last_visible_y
1786 && it.bidi_p && it.bidi_it.scan_dir == -1
1787 && IT_CHARPOS (it) < charpos)
1788 {
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799 int ten_more_lines = 10 * default_line_pixel_height (w);
1800
1801 move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1,
1802 MOVE_TO_POS | MOVE_TO_Y);
1803 if (it.current_y > top_y)
1804 visible_p = false;
1805
1806 }
1807 RESTORE_IT (&it, &save_it, save_it_data);
1808 if (visible_p)
1809 {
1810 if (it.method == GET_FROM_DISPLAY_VECTOR)
1811 {
1812
1813
1814 if (charpos < 2 || top.charpos >= charpos)
1815 top_x = it.glyph_row->x;
1816 else
1817 {
1818 struct it it2, it2_prev;
1819
1820
1821
1822
1823
1824
1825 start_display (&it2, w, top);
1826 it2.glyph_row = NULL;
1827 move_it_to (&it2, charpos - 1, -1, -1, -1, MOVE_TO_POS);
1828
1829
1830
1831
1832 if (IT_CHARPOS (it2) != charpos - 1)
1833 it2_prev = it2;
1834 else
1835 {
1836
1837
1838
1839 do {
1840 get_next_display_element (&it2);
1841 PRODUCE_GLYPHS (&it2);
1842 it2_prev = it2;
1843 set_iterator_to_next (&it2, true);
1844 } while (it2.method == GET_FROM_DISPLAY_VECTOR
1845 && IT_CHARPOS (it2) < charpos);
1846 }
1847 if (ITERATOR_AT_END_OF_LINE_P (&it2_prev)
1848 || it2_prev.current_x > it2_prev.last_visible_x)
1849 top_x = it.glyph_row->x;
1850 else
1851 {
1852 top_x = it2_prev.current_x;
1853 top_y = it2_prev.current_y;
1854 }
1855 }
1856 }
1857 else if (IT_CHARPOS (it) != charpos)
1858 {
1859 Lisp_Object cpos = make_fixnum (charpos);
1860 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
1861 Lisp_Object string = string_from_display_spec (spec);
1862 struct text_pos tpos;
1863 bool newline_in_string
1864 = (STRINGP (string)
1865 && memchr (SDATA (string), '\n', SBYTES (string)));
1866
1867 SET_TEXT_POS (tpos, charpos, CHAR_TO_BYTE (charpos));
1868 bool replacing_spec_p
1869 = (!NILP (spec)
1870 && handle_display_spec (NULL, spec, Qnil, Qnil, &tpos,
1871 charpos, FRAME_WINDOW_P (it.f)));
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888 if (replacing_spec_p)
1889 {
1890 Lisp_Object startpos, endpos;
1891 EMACS_INT start, end;
1892 struct it it3;
1893
1894
1895
1896 endpos =
1897 Fnext_single_char_property_change (cpos, Qdisplay,
1898 Qnil, Qnil);
1899 startpos =
1900 Fprevious_single_char_property_change (endpos, Qdisplay,
1901 Qnil, Qnil);
1902 start = XFIXNAT (startpos);
1903 end = XFIXNAT (endpos);
1904
1905
1906 start_display (&it3, w, top);
1907 if (start > CHARPOS (top))
1908 move_it_to (&it3, start - 1, -1, -1, -1, MOVE_TO_POS);
1909
1910
1911
1912
1913 if (it3.method == GET_FROM_BUFFER
1914 && (it3.c == '\n'
1915 || FETCH_BYTE (IT_BYTEPOS (it3)) == '\n'))
1916 move_it_by_lines (&it3, 1);
1917 else if (move_it_in_display_line_to (&it3, -1,
1918 it3.current_x
1919 + it3.pixel_width,
1920 MOVE_TO_X)
1921 == MOVE_LINE_CONTINUED)
1922 {
1923 move_it_by_lines (&it3, 1);
1924
1925
1926
1927 if (it3.line_wrap == WORD_WRAP)
1928 move_it_by_lines (&it3, -1);
1929 }
1930
1931
1932
1933 top_y = it3.current_y;
1934 if (it3.bidi_p)
1935 {
1936
1937
1938
1939
1940
1941 start_display (&it3, w, top);
1942 move_it_to (&it3, end + 1, -1, -1, -1, MOVE_TO_POS);
1943 if (it3.current_y < top_y)
1944 top_y = it3.current_y;
1945 }
1946
1947
1948
1949 start_display (&it3, w, top);
1950 it3.glyph_row = NULL;
1951 move_it_to (&it3, -1, 0, top_y, -1, MOVE_TO_X | MOVE_TO_Y);
1952
1953
1954
1955
1956
1957
1958
1959 bool it3_moved = false;
1960 int top_x_before_string = it3.current_x;
1961
1962
1963
1964
1965
1966 while (get_next_display_element (&it3))
1967 {
1968 if (!EQ (it3.object, string))
1969 top_x_before_string = it3.current_x;
1970 PRODUCE_GLYPHS (&it3);
1971 if ((it3.bidi_it.scan_dir == 1
1972 && IT_CHARPOS (it3) >= charpos)
1973 || (it3.bidi_it.scan_dir == -1
1974 && IT_CHARPOS (it3) <= charpos)
1975 || ITERATOR_AT_END_OF_LINE_P (&it3))
1976 break;
1977 it3_moved = true;
1978 set_iterator_to_next (&it3, false);
1979 }
1980 top_x = it3.current_x - it3.pixel_width;
1981
1982
1983
1984 if (!it3.line_number_produced_p)
1985 {
1986 if (it3.lnum_pixel_width > 0)
1987 {
1988 top_x += it3.lnum_pixel_width;
1989 top_x_before_string += it3.lnum_pixel_width;
1990 }
1991 else if (it.line_number_produced_p)
1992 {
1993 top_x += it.lnum_pixel_width;
1994 top_x_before_string += it3.lnum_pixel_width;
1995 }
1996 }
1997
1998
1999
2000
2001
2002
2003 if (it3_moved
2004 && newline_in_string
2005 && IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
2006 top_x = top_x_before_string;
2007 }
2008 }
2009
2010 *x = top_x;
2011
2012
2013
2014
2015 if (it.ascent == 0 && it.what == IT_IMAGE
2016 && it.method != GET_FROM_IMAGE
2017 && it.image_id < 0
2018 && it.max_ascent > 0)
2019 *y = max (top_y, window_top_y);
2020 else
2021 *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
2022 *rtop = max (0, window_top_y - top_y);
2023 *rbot = max (0, bottom_y - it.last_visible_y);
2024 *rowh = max (0, (min (bottom_y, it.last_visible_y)
2025 - max (top_y, window_top_y)));
2026 *vpos = it.vpos;
2027 if (it.bidi_it.paragraph_dir == R2L)
2028 r2l = true;
2029 }
2030 }
2031 else
2032 {
2033
2034
2035
2036 struct it it2;
2037 void *it2data = NULL;
2038
2039 SAVE_IT (it2, it, it2data);
2040 if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
2041 move_it_by_lines (&it, 1);
2042 if (charpos < IT_CHARPOS (it)
2043 || (it.what == IT_EOB && charpos == IT_CHARPOS (it)))
2044 {
2045 visible_p = true;
2046 RESTORE_IT (&it2, &it2, it2data);
2047 move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
2048 *x = it2.current_x;
2049 if (it2.ascent == 0 && it2.what == IT_IMAGE
2050 && it2.method != GET_FROM_IMAGE
2051 && it2.image_id < 0
2052 && it2.max_ascent > 0)
2053 *y = it2.current_y;
2054 else
2055 *y = it2.current_y + it2.max_ascent - it2.ascent;
2056 *rtop = max (0, -it2.current_y);
2057 *rbot = max (0, ((it2.current_y + it2.max_ascent + it2.max_descent)
2058 - it.last_visible_y));
2059 *rowh = max (0, (min (it2.current_y + it2.max_ascent + it2.max_descent,
2060 it.last_visible_y)
2061 - max (max (it2.current_y,
2062 WINDOW_TAB_LINE_HEIGHT (w)),
2063 WINDOW_HEADER_LINE_HEIGHT (w))));
2064 *vpos = it2.vpos;
2065 if (it2.bidi_it.paragraph_dir == R2L)
2066 r2l = true;
2067 }
2068 else
2069 bidi_unshelve_cache (it2data, true);
2070 }
2071 bidi_unshelve_cache (itdata, false);
2072
2073 if (old_buffer)
2074 set_buffer_internal_1 (old_buffer);
2075
2076 if (visible_p)
2077 {
2078 if (w->hscroll > 0)
2079 *x -=
2080 window_hscroll_limited (w, WINDOW_XFRAME (w))
2081 * WINDOW_FRAME_COLUMN_WIDTH (w);
2082
2083
2084
2085
2086
2087 if (r2l)
2088 *x = window_box_width (w, TEXT_AREA) - *x - 1;
2089 }
2090
2091 #if false
2092
2093 if (visible_p)
2094 fprintf (stderr, "+pv pt=%d vs=%d --> x=%d y=%d rt=%d rb=%d rh=%d vp=%d\n",
2095 charpos, w->vscroll, *x, *y, *rtop, *rbot, *rowh, *vpos);
2096 else
2097 fprintf (stderr, "-pv pt=%d vs=%d\n", charpos, w->vscroll);
2098 #endif
2099
2100
2101 w->mode_line_height = prev_mode_line_height;
2102 w->header_line_height = prev_header_line_height;
2103 w->tab_line_height = prev_tab_line_height;
2104
2105 return visible_p;
2106 }
2107
2108
2109
2110
2111
2112
2113
2114 static int
2115 check_char_and_length (const unsigned char *str, int *len)
2116 {
2117 int c = string_char_and_length (str, len);
2118 if (!CHAR_VALID_P (c))
2119
2120
2121
2122 c = '?';
2123
2124 return c;
2125 }
2126
2127
2128
2129
2130
2131
2132 static struct text_pos
2133 string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t nchars)
2134 {
2135 eassert (STRINGP (string) && nchars >= 0);
2136
2137 if (STRING_MULTIBYTE (string))
2138 {
2139 const unsigned char *p = SDATA (string) + BYTEPOS (pos);
2140
2141 while (nchars--)
2142 {
2143 int len = BYTES_BY_CHAR_HEAD (*p);
2144 p += len;
2145 CHARPOS (pos) += 1;
2146 BYTEPOS (pos) += len;
2147 }
2148 }
2149 else
2150 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
2151
2152 return pos;
2153 }
2154
2155
2156
2157
2158
2159 static struct text_pos
2160 string_pos (ptrdiff_t charpos, Lisp_Object string)
2161 {
2162 struct text_pos pos;
2163 eassert (STRINGP (string));
2164 eassert (charpos >= 0);
2165 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
2166 return pos;
2167 }
2168
2169
2170
2171
2172
2173
2174 static struct text_pos
2175 c_string_pos (ptrdiff_t charpos, const char *s, bool multibyte_p)
2176 {
2177 struct text_pos pos;
2178
2179 eassert (s != NULL);
2180 eassert (charpos >= 0);
2181
2182 if (multibyte_p)
2183 {
2184 SET_TEXT_POS (pos, 0, 0);
2185 while (charpos--)
2186 {
2187 int len = BYTES_BY_CHAR_HEAD (*s);
2188 s += len;
2189 CHARPOS (pos) += 1;
2190 BYTEPOS (pos) += len;
2191 }
2192 }
2193 else
2194 SET_TEXT_POS (pos, charpos, charpos);
2195
2196 return pos;
2197 }
2198
2199
2200
2201
2202
2203 static ptrdiff_t
2204 number_of_chars (const char *s, bool multibyte_p)
2205 {
2206 ptrdiff_t nchars;
2207
2208 if (multibyte_p)
2209 {
2210 ptrdiff_t rest = strlen (s);
2211 const unsigned char *p = (const unsigned char *) s;
2212
2213 for (nchars = 0; rest > 0; ++nchars)
2214 {
2215 int len = BYTES_BY_CHAR_HEAD (*p);
2216 rest -= len, p += len;
2217 }
2218 }
2219 else
2220 nchars = strlen (s);
2221
2222 return nchars;
2223 }
2224
2225
2226
2227
2228
2229
2230 static void
2231 compute_string_pos (struct text_pos *newpos, struct text_pos pos, Lisp_Object string)
2232 {
2233 eassert (STRINGP (string));
2234 eassert (CHARPOS (*newpos) >= CHARPOS (pos));
2235
2236 if (STRING_MULTIBYTE (string))
2237 *newpos = string_pos_nchars_ahead (pos, string,
2238 CHARPOS (*newpos) - CHARPOS (pos));
2239 else
2240 BYTEPOS (*newpos) = CHARPOS (*newpos);
2241 }
2242
2243
2244
2245
2246
2247 int
2248 estimate_mode_line_height (struct frame *f, enum face_id face_id)
2249 {
2250 #ifdef HAVE_WINDOW_SYSTEM
2251 if (FRAME_WINDOW_P (f))
2252 {
2253 int height = FONT_HEIGHT (FRAME_FONT (f));
2254
2255
2256
2257 if (FRAME_FACE_CACHE (f))
2258 {
2259 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
2260 if (face)
2261 {
2262 if (face->font)
2263 height = normal_char_height (face->font, -1);
2264 if (face->box_horizontal_line_width > 0)
2265 height += 2 * face->box_horizontal_line_width;
2266 }
2267 }
2268
2269 return height;
2270 }
2271 #endif
2272
2273 return 1;
2274 }
2275
2276
2277
2278
2279
2280
2281 void
2282 pixel_to_glyph_coords (struct frame *f, int pix_x, int pix_y, int *x, int *y,
2283 NativeRectangle *bounds, bool noclip)
2284 {
2285
2286 #ifdef HAVE_WINDOW_SYSTEM
2287 if (FRAME_WINDOW_P (f))
2288 {
2289
2290
2291 if (pix_x < 0)
2292 pix_x -= FRAME_COLUMN_WIDTH (f) - 1;
2293 if (pix_y < 0)
2294 pix_y -= FRAME_LINE_HEIGHT (f) - 1;
2295
2296 pix_x = FRAME_PIXEL_X_TO_COL (f, pix_x);
2297 pix_y = FRAME_PIXEL_Y_TO_LINE (f, pix_y);
2298
2299 if (bounds)
2300 STORE_NATIVE_RECT (*bounds,
2301 FRAME_COL_TO_PIXEL_X (f, pix_x),
2302 FRAME_LINE_TO_PIXEL_Y (f, pix_y),
2303 FRAME_COLUMN_WIDTH (f) - 1,
2304 FRAME_LINE_HEIGHT (f) - 1);
2305
2306
2307 if (!noclip)
2308 {
2309 if (pix_x < 0)
2310 pix_x = 0;
2311 else if (pix_x > FRAME_TOTAL_COLS (f))
2312 pix_x = FRAME_TOTAL_COLS (f);
2313
2314 if (pix_y < 0)
2315 pix_y = 0;
2316 else if (pix_y > FRAME_TOTAL_LINES (f))
2317 pix_y = FRAME_TOTAL_LINES (f);
2318 }
2319 }
2320 #endif
2321
2322 *x = pix_x;
2323 *y = pix_y;
2324 }
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335 struct glyph *
2336 x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos,
2337 int *dx, int *dy, int *area)
2338 {
2339 struct glyph *glyph, *end;
2340 struct glyph_row *row = NULL;
2341 int x0, i;
2342
2343
2344 for (i = 0; i < w->current_matrix->nrows; ++i)
2345 {
2346 row = MATRIX_ROW (w->current_matrix, i);
2347 if (!row->enabled_p)
2348 return NULL;
2349 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
2350 break;
2351 }
2352
2353 *vpos = i;
2354 *hpos = 0;
2355
2356
2357 if (i == w->current_matrix->nrows)
2358 return NULL;
2359
2360
2361 if (w->pseudo_window_p)
2362 {
2363 *area = TEXT_AREA;
2364 x0 = 0;
2365 }
2366 else
2367 {
2368 if (x < window_box_left_offset (w, TEXT_AREA))
2369 {
2370 *area = LEFT_MARGIN_AREA;
2371 x0 = window_box_left_offset (w, LEFT_MARGIN_AREA);
2372 }
2373 else if (x < window_box_right_offset (w, TEXT_AREA))
2374 {
2375 *area = TEXT_AREA;
2376 x0 = window_box_left_offset (w, TEXT_AREA) + min (row->x, 0);
2377 }
2378 else
2379 {
2380 *area = RIGHT_MARGIN_AREA;
2381 x0 = window_box_left_offset (w, RIGHT_MARGIN_AREA);
2382 }
2383 }
2384
2385
2386 glyph = row->glyphs[*area];
2387 end = glyph + row->used[*area];
2388 x -= x0;
2389 while (glyph < end && x >= glyph->pixel_width)
2390 {
2391 x -= glyph->pixel_width;
2392 ++glyph;
2393 }
2394
2395 if (glyph == end)
2396 return NULL;
2397
2398 if (dx)
2399 {
2400 *dx = x;
2401 *dy = y - (row->y + row->ascent - glyph->ascent);
2402 }
2403
2404 *hpos = glyph - row->glyphs[*area];
2405 return glyph;
2406 }
2407
2408
2409
2410
2411 static void
2412 frame_to_window_pixel_xy (struct window *w, int *x, int *y)
2413 {
2414 if (w->pseudo_window_p)
2415 {
2416
2417
2418 struct frame *f = XFRAME (w->frame);
2419 *x -= FRAME_INTERNAL_BORDER_WIDTH (f);
2420 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2421 }
2422 else
2423 {
2424 *x -= WINDOW_LEFT_EDGE_X (w);
2425 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2426 }
2427 }
2428
2429 #ifdef HAVE_WINDOW_SYSTEM
2430
2431
2432
2433
2434
2435 int
2436 get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int n)
2437 {
2438 Emacs_Rectangle r;
2439
2440 if (n <= 0)
2441 return 0;
2442
2443 if (s->row->full_width_p)
2444 {
2445
2446 r.x = WINDOW_LEFT_EDGE_X (s->w);
2447 if (s->row->mode_line_p)
2448 r.width = WINDOW_PIXEL_WIDTH (s->w) - WINDOW_RIGHT_DIVIDER_WIDTH (s->w);
2449 else
2450 r.width = WINDOW_PIXEL_WIDTH (s->w);
2451
2452
2453
2454 if (s->w->pseudo_window_p)
2455 r.height = s->row->visible_height;
2456 else
2457 r.height = s->height;
2458 }
2459 else
2460 {
2461
2462 r.x = window_box_left (s->w, s->area);
2463 r.width = window_box_width (s->w, s->area);
2464 r.height = s->row->visible_height;
2465 }
2466
2467 if (s->clip_head)
2468 if (r.x < s->clip_head->x)
2469 {
2470 if (r.width >= s->clip_head->x - r.x)
2471 r.width -= s->clip_head->x - r.x;
2472 else
2473 r.width = 0;
2474 r.x = s->clip_head->x;
2475 }
2476 if (s->clip_tail)
2477 if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width)
2478 {
2479 if (s->clip_tail->x + s->clip_tail->background_width >= r.x)
2480 r.width = s->clip_tail->x + s->clip_tail->background_width - r.x;
2481 else
2482 r.width = 0;
2483 }
2484
2485
2486
2487
2488 if (s->for_overlaps)
2489 {
2490 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2491 r.height = window_text_bottom_y (s->w) - r.y;
2492
2493
2494
2495
2496
2497
2498 if (s->for_overlaps & OVERLAPS_ERASED_CURSOR)
2499 {
2500 Emacs_Rectangle rc, r_save = r;
2501
2502 rc.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (s->w, s->w->phys_cursor.x);
2503 rc.y = s->w->phys_cursor.y;
2504 rc.width = s->w->phys_cursor_width;
2505 rc.height = s->w->phys_cursor_height;
2506
2507 gui_intersect_rectangles (&r_save, &rc, &r);
2508 }
2509 }
2510 else
2511 {
2512
2513
2514
2515 if (!s->row->full_width_p
2516 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2517 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2518 else
2519 r.y = max (0, s->row->y);
2520 }
2521
2522 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
2523
2524
2525
2526 if (s->hl == DRAW_CURSOR)
2527 {
2528 struct glyph *glyph = s->first_glyph;
2529 int height, max_y;
2530
2531 if (s->x > r.x)
2532 {
2533 if (r.width >= s->x - r.x)
2534 r.width -= s->x - r.x;
2535 else
2536 r.width = 0;
2537 r.x = s->x;
2538 }
2539 r.width = min (r.width, glyph->pixel_width);
2540
2541
2542 height = min (glyph->ascent + glyph->descent,
2543 min (FRAME_LINE_HEIGHT (s->f), s->row->visible_height));
2544 max_y = window_text_bottom_y (s->w) - height;
2545 max_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, max_y);
2546 if (s->ybase - glyph->ascent > max_y)
2547 {
2548 r.y = max_y;
2549 r.height = height;
2550 }
2551 else
2552 {
2553
2554 height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
2555 if (height < r.height)
2556 {
2557 max_y = r.y + r.height;
2558 r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height));
2559 r.height = min (max_y - r.y, height);
2560 }
2561 }
2562 }
2563
2564 if (s->row->clip)
2565 {
2566 Emacs_Rectangle r_save = r;
2567
2568 if (! gui_intersect_rectangles (&r_save, s->row->clip, &r))
2569 r.width = 0;
2570 }
2571
2572 if ((s->for_overlaps & OVERLAPS_BOTH) == 0
2573 || ((s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1))
2574 {
2575 #ifdef CONVERT_FROM_EMACS_RECT
2576 CONVERT_FROM_EMACS_RECT (r, *rects);
2577 #else
2578 *rects = r;
2579 #endif
2580 return 1;
2581 }
2582 else
2583 {
2584
2585
2586
2587
2588 #ifdef CONVERT_FROM_EMACS_RECT
2589 Emacs_Rectangle rs[2];
2590 #else
2591 Emacs_Rectangle *rs = rects;
2592 #endif
2593 int i = 0, row_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, s->row->y);
2594
2595 if (s->for_overlaps & OVERLAPS_PRED)
2596 {
2597 rs[i] = r;
2598 if (r.y + r.height > row_y)
2599 {
2600 if (r.y < row_y)
2601 rs[i].height = row_y - r.y;
2602 else
2603 rs[i].height = 0;
2604 }
2605 i++;
2606 }
2607 if (s->for_overlaps & OVERLAPS_SUCC)
2608 {
2609 rs[i] = r;
2610 if (r.y < row_y + s->row->visible_height)
2611 {
2612 if (r.y + r.height > row_y + s->row->visible_height)
2613 {
2614 rs[i].y = row_y + s->row->visible_height;
2615 rs[i].height = r.y + r.height - rs[i].y;
2616 }
2617 else
2618 rs[i].height = 0;
2619 }
2620 i++;
2621 }
2622
2623 n = i;
2624 #ifdef CONVERT_FROM_EMACS_RECT
2625 for (i = 0; i < n; i++)
2626 CONVERT_FROM_EMACS_RECT (rs[i], rects[i]);
2627 #endif
2628 return n;
2629 }
2630 }
2631
2632
2633
2634
2635 void
2636 get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2637 {
2638 get_glyph_string_clip_rects (s, nr, 1);
2639 }
2640
2641
2642
2643
2644
2645
2646
2647 void
2648 get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
2649 struct glyph *glyph, int *xp, int *yp, int *heightp)
2650 {
2651 struct frame *f = XFRAME (WINDOW_FRAME (w));
2652 int x, y, wd, h, h0, y0, ascent;
2653
2654
2655
2656
2657
2658 wd = glyph->pixel_width;
2659
2660 x = w->phys_cursor.x;
2661 if (x < 0)
2662 {
2663 wd += x;
2664 x = 0;
2665 }
2666
2667 if (glyph->type == STRETCH_GLYPH
2668 && !x_stretch_cursor_p)
2669 wd = min (FRAME_COLUMN_WIDTH (f), wd);
2670 w->phys_cursor_width = wd;
2671
2672
2673
2674 y = w->phys_cursor.y;
2675 ascent = row->ascent;
2676
2677
2678
2679 if (!row->ends_at_zv_p && row->ascent < glyph->ascent)
2680 {
2681 y -= glyph->ascent - row->ascent;
2682 ascent = glyph->ascent;
2683 }
2684
2685
2686 h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height);
2687
2688 h = max (h0, ascent + glyph->descent);
2689
2690
2691 h = min (h, row->height);
2692 h0 = min (h0, ascent + glyph->descent);
2693
2694 y0 = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
2695 if (y < y0)
2696 {
2697 h = max (h - (y0 - y) + 1, h0);
2698 y = y0 - 1;
2699 }
2700 else
2701 {
2702 y0 = window_text_bottom_y (w) - h0;
2703 if (y > y0)
2704 {
2705 h += y - y0;
2706 y = y0;
2707 }
2708 }
2709
2710 *xp = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
2711 *yp = WINDOW_TO_FRAME_PIXEL_Y (w, y);
2712 *heightp = h;
2713 }
2714
2715
2716
2717
2718
2719 void
2720 remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
2721 {
2722 Lisp_Object window;
2723 struct window *w;
2724 struct glyph_row *r, *gr, *end_row;
2725 enum window_part part;
2726 enum glyph_row_area area;
2727 int x, y, width, height;
2728
2729 if (mouse_fine_grained_tracking)
2730 {
2731 STORE_NATIVE_RECT (*rect, gx, gy, 1, 1);
2732 return;
2733 }
2734
2735
2736
2737
2738 if (window_resize_pixelwise)
2739 {
2740 width = height = 1;
2741 goto virtual_glyph;
2742 }
2743 else if (!f->glyphs_initialized_p
2744 || (window = window_from_coordinates (f, gx, gy, &part, false, false),
2745 NILP (window)))
2746 {
2747 width = FRAME_SMALLEST_CHAR_WIDTH (f);
2748 height = FRAME_SMALLEST_FONT_HEIGHT (f);
2749 goto virtual_glyph;
2750 }
2751
2752 w = XWINDOW (window);
2753 width = WINDOW_FRAME_COLUMN_WIDTH (w);
2754 height = WINDOW_FRAME_LINE_HEIGHT (w);
2755
2756 x = window_relative_x_coord (w, part, gx);
2757 y = gy - WINDOW_TOP_EDGE_Y (w);
2758
2759 r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
2760 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
2761
2762 if (w->pseudo_window_p)
2763 {
2764 area = TEXT_AREA;
2765 part = ON_MODE_LINE;
2766 goto text_glyph;
2767 }
2768
2769 switch (part)
2770 {
2771 case ON_LEFT_MARGIN:
2772 area = LEFT_MARGIN_AREA;
2773 goto text_glyph;
2774
2775 case ON_RIGHT_MARGIN:
2776 area = RIGHT_MARGIN_AREA;
2777 goto text_glyph;
2778
2779 case ON_TAB_LINE:
2780 case ON_HEADER_LINE:
2781 case ON_MODE_LINE:
2782 gr = (part == ON_TAB_LINE
2783 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
2784 : (part == ON_HEADER_LINE
2785 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
2786 : MATRIX_MODE_LINE_ROW (w->current_matrix)));
2787 gy = gr->y;
2788 area = TEXT_AREA;
2789 goto text_glyph_row_found;
2790
2791 case ON_TEXT:
2792 area = TEXT_AREA;
2793
2794 text_glyph:
2795 gr = 0; gy = 0;
2796 for (; r <= end_row && r->enabled_p; ++r)
2797 if (r->y + r->height > y)
2798 {
2799 gr = r; gy = r->y;
2800 break;
2801 }
2802
2803 text_glyph_row_found:
2804 if (gr && gy <= y)
2805 {
2806 struct glyph *g = gr->glyphs[area];
2807 struct glyph *end = g + gr->used[area];
2808
2809 height = gr->height;
2810 for (gx = gr->x; g < end; gx += g->pixel_width, ++g)
2811 if (gx + g->pixel_width > x)
2812 break;
2813
2814 if (g < end)
2815 {
2816 if (g->type == IMAGE_GLYPH)
2817 {
2818
2819
2820 STORE_NATIVE_RECT (*rect, 0, 0, 0, 0);
2821 return;
2822 }
2823 width = g->pixel_width;
2824 }
2825 else
2826 {
2827
2828 x -= gx;
2829 gx += (x / width) * width;
2830 }
2831
2832 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2833 && part != ON_TAB_LINE)
2834 {
2835 gx += window_box_left_offset (w, area);
2836
2837
2838 height = min (height,
2839 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2840 }
2841 }
2842 else
2843 {
2844
2845 gx = (x / width) * width;
2846 y -= gy;
2847 gy += (y / height) * height;
2848 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2849 && part != ON_TAB_LINE)
2850
2851 height = min (height,
2852 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2853 }
2854 break;
2855
2856 case ON_LEFT_FRINGE:
2857 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2858 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
2859 : window_box_right_offset (w, LEFT_MARGIN_AREA));
2860 width = WINDOW_LEFT_FRINGE_WIDTH (w);
2861 goto row_glyph;
2862
2863 case ON_RIGHT_FRINGE:
2864 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2865 ? window_box_right_offset (w, RIGHT_MARGIN_AREA)
2866 : window_box_right_offset (w, TEXT_AREA));
2867 if (WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
2868 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
2869 && !WINDOW_RIGHTMOST_P (w))
2870 if (gx < WINDOW_PIXEL_WIDTH (w) - width)
2871
2872
2873 width = WINDOW_RIGHT_FRINGE_WIDTH (w) - width;
2874 else
2875 width = WINDOW_PIXEL_WIDTH (w) - gx;
2876 else
2877 width = WINDOW_RIGHT_FRINGE_WIDTH (w);
2878
2879 goto row_glyph;
2880
2881 case ON_VERTICAL_BORDER:
2882 gx = WINDOW_PIXEL_WIDTH (w) - width;
2883 goto row_glyph;
2884
2885 case ON_VERTICAL_SCROLL_BAR:
2886 gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
2887 ? 0
2888 : (window_box_right_offset (w, RIGHT_MARGIN_AREA)
2889 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2890 ? WINDOW_RIGHT_FRINGE_WIDTH (w)
2891 : 0)));
2892 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
2893
2894 row_glyph:
2895 gr = 0, gy = 0;
2896 for (; r <= end_row && r->enabled_p; ++r)
2897 if (r->y + r->height > y)
2898 {
2899 gr = r; gy = r->y;
2900 break;
2901 }
2902
2903 if (gr && gy <= y)
2904 height = gr->height;
2905 else
2906 {
2907
2908 y -= gy;
2909 gy += (y / height) * height;
2910 }
2911 break;
2912
2913 case ON_RIGHT_DIVIDER:
2914 gx = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
2915 width = WINDOW_RIGHT_DIVIDER_WIDTH (w);
2916 gy = 0;
2917
2918 height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2919 goto add_edge;
2920
2921 case ON_BOTTOM_DIVIDER:
2922 gx = 0;
2923 width = WINDOW_PIXEL_WIDTH (w);
2924 gy = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2925 height = WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2926 goto add_edge;
2927
2928 default:
2929 ;
2930 virtual_glyph:
2931
2932
2933
2934
2935
2936
2937 if (gx < 0)
2938 gx -= width - 1;
2939 if (gy < 0)
2940 gy -= height - 1;
2941
2942 gx = (gx / width) * width;
2943 gy = (gy / height) * height;
2944
2945 goto store_rect;
2946 }
2947
2948 add_edge:
2949 gx += WINDOW_LEFT_EDGE_X (w);
2950 gy += WINDOW_TOP_EDGE_Y (w);
2951
2952 store_rect:
2953 STORE_NATIVE_RECT (*rect, gx, gy, width, height);
2954
2955
2956 #if false && defined HAVE_X_WINDOWS
2957 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
2958 f->output_data.x->normal_gc,
2959 gx, gy, width, height);
2960 #endif
2961 }
2962
2963
2964 #endif
2965
2966 static void
2967 adjust_window_ends (struct window *w, struct glyph_row *row, bool current)
2968 {
2969 eassert (w);
2970 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
2971 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
2972 w->window_end_vpos
2973 = MATRIX_ROW_VPOS (row, current ? w->current_matrix : w->desired_matrix);
2974 }
2975
2976 static bool
2977 hscrolling_current_line_p (struct window *w)
2978 {
2979 return (!w->suspend_auto_hscroll
2980 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
2981 Qcurrent_line));
2982 }
2983
2984
2985
2986
2987
2988
2989
2990 static Lisp_Object
2991 safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
2992 {
2993 add_to_log ("Error during redisplay: %S signaled %S",
2994 Flist (nargs, args), arg);
2995 return Qnil;
2996 }
2997
2998
2999
3000
3001
3002 static Lisp_Object
3003 safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
3004 {
3005 Lisp_Object val;
3006
3007 if (inhibit_eval_during_redisplay)
3008 val = Qnil;
3009 else
3010 {
3011 ptrdiff_t i;
3012 specpdl_ref count = SPECPDL_INDEX ();
3013 Lisp_Object *args;
3014 USE_SAFE_ALLOCA;
3015 SAFE_ALLOCA_LISP (args, nargs);
3016
3017 args[0] = func;
3018 for (i = 1; i < nargs; i++)
3019 args[i] = va_arg (ap, Lisp_Object);
3020
3021 specbind (Qinhibit_redisplay, Qt);
3022 if (inhibit_quit)
3023 specbind (Qinhibit_quit, Qt);
3024
3025
3026 val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
3027 safe_eval_handler);
3028 val = SAFE_FREE_UNBIND_TO (count, val);
3029 }
3030
3031 return val;
3032 }
3033
3034 Lisp_Object
3035 safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
3036 {
3037 Lisp_Object retval;
3038 va_list ap;
3039
3040 va_start (ap, func);
3041 retval = safe__call (false, nargs, func, ap);
3042 va_end (ap);
3043 return retval;
3044 }
3045
3046
3047
3048
3049 Lisp_Object
3050 safe_call1 (Lisp_Object fn, Lisp_Object arg)
3051 {
3052 return safe_call (2, fn, arg);
3053 }
3054
3055 static Lisp_Object
3056 safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
3057 {
3058 Lisp_Object retval;
3059 va_list ap;
3060
3061 va_start (ap, fn);
3062 retval = safe__call (inhibit_quit, 2, fn, ap);
3063 va_end (ap);
3064 return retval;
3065 }
3066
3067 Lisp_Object
3068 safe_eval (Lisp_Object sexpr)
3069 {
3070 return safe__call1 (false, Qeval, sexpr);
3071 }
3072
3073 static Lisp_Object
3074 safe__eval (bool inhibit_quit, Lisp_Object sexpr)
3075 {
3076 return safe__call1 (inhibit_quit, Qeval, sexpr);
3077 }
3078
3079
3080
3081
3082 Lisp_Object
3083 safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
3084 {
3085 return safe_call (3, fn, arg1, arg2);
3086 }
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097 static void
3098 CHECK_IT (struct it *it)
3099 {
3100 #if false
3101 if (it->method == GET_FROM_STRING)
3102 {
3103 eassert (STRINGP (it->string));
3104 eassert (IT_STRING_CHARPOS (*it) >= 0);
3105 }
3106 else
3107 {
3108 eassert (IT_STRING_CHARPOS (*it) < 0);
3109 if (it->method == GET_FROM_BUFFER)
3110 {
3111
3112 eassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
3113 }
3114 }
3115
3116 if (it->dpvec)
3117 eassert (it->current.dpvec_index >= 0);
3118 else
3119 eassert (it->current.dpvec_index < 0);
3120 #endif
3121 }
3122
3123
3124
3125
3126
3127 static void
3128 CHECK_WINDOW_END (struct window *w)
3129 {
3130 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3131 if (!MINI_WINDOW_P (w) && w->window_end_valid)
3132 {
3133 struct glyph_row *row;
3134 eassert ((row = MATRIX_ROW (w->current_matrix, w->window_end_vpos),
3135 !row->enabled_p
3136 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
3137 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
3138 }
3139 #endif
3140 }
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165 void
3166 init_iterator (struct it *it, struct window *w,
3167 ptrdiff_t charpos, ptrdiff_t bytepos,
3168 struct glyph_row *row, enum face_id base_face_id)
3169 {
3170 enum face_id remapped_base_face_id = base_face_id;
3171 int body_width = 0, body_height = 0;
3172
3173
3174 eassert (w != NULL && it != NULL);
3175 eassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
3176 && charpos <= ZV));
3177
3178
3179
3180
3181
3182 if (!inhibit_free_realized_faces)
3183 {
3184 if (face_change)
3185 {
3186 face_change = false;
3187 XFRAME (w->frame)->face_change = 0;
3188 free_all_realized_faces (Qnil);
3189 }
3190 else if (XFRAME (w->frame)->face_change)
3191 {
3192 XFRAME (w->frame)->face_change = 0;
3193 free_all_realized_faces (w->frame);
3194 }
3195 }
3196
3197
3198 if (! NILP (Vface_remapping_alist))
3199 remapped_base_face_id
3200 = lookup_basic_face (w, XFRAME (w->frame), base_face_id);
3201
3202
3203
3204 if (row == NULL)
3205 {
3206 if (base_face_id == MODE_LINE_ACTIVE_FACE_ID
3207 || base_face_id == MODE_LINE_INACTIVE_FACE_ID)
3208 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
3209 else if (base_face_id == TAB_LINE_FACE_ID)
3210 row = MATRIX_TAB_LINE_ROW (w->desired_matrix);
3211 else if (base_face_id == HEADER_LINE_FACE_ID)
3212 {
3213
3214 w->desired_matrix->tab_line_p = window_wants_tab_line (w);
3215 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
3216 }
3217 }
3218
3219
3220
3221 memclear (it, sizeof *it);
3222 it->current.overlay_string_index = -1;
3223 it->current.dpvec_index = -1;
3224 it->base_face_id = remapped_base_face_id;
3225 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
3226 it->paragraph_embedding = L2R;
3227 it->bidi_it.w = w;
3228
3229
3230 XSETWINDOW (it->window, w);
3231 it->w = w;
3232 it->f = XFRAME (w->frame);
3233
3234 it->cmp_it.id = -1;
3235 it->cmp_it.parent_it = it;
3236
3237 if (max_redisplay_ticks > 0)
3238 update_redisplay_ticks (0, w);
3239
3240
3241 if (base_face_id == DEFAULT_FACE_ID
3242 && FRAME_WINDOW_P (it->f))
3243 {
3244 if (FIXNATP (BVAR (current_buffer, extra_line_spacing)))
3245 it->extra_line_spacing = XFIXNAT (BVAR (current_buffer, extra_line_spacing));
3246 else if (FLOATP (BVAR (current_buffer, extra_line_spacing)))
3247 it->extra_line_spacing = (XFLOAT_DATA (BVAR (current_buffer, extra_line_spacing))
3248 * FRAME_LINE_HEIGHT (it->f));
3249 else if (it->f->extra_line_spacing > 0)
3250 it->extra_line_spacing = it->f->extra_line_spacing;
3251 }
3252
3253
3254
3255
3256
3257 if (FRAME_FACE_CACHE (it->f) == NULL)
3258 init_frame_faces (it->f);
3259 if (FRAME_FACE_CACHE (it->f)->used == 0)
3260 recompute_basic_faces (it->f);
3261
3262 it->override_ascent = -1;
3263
3264
3265 it->ctl_arrow_p = !NILP (BVAR (current_buffer, ctl_arrow));
3266
3267
3268
3269
3270 it->selective = (FIXNUMP (BVAR (current_buffer, selective_display))
3271 ? (clip_to_bounds
3272 (-1, XFIXNUM (BVAR (current_buffer, selective_display)),
3273 PTRDIFF_MAX))
3274 : (!NILP (BVAR (current_buffer, selective_display))
3275 ? -1 : 0));
3276 it->selective_display_ellipsis_p
3277 = !NILP (BVAR (current_buffer, selective_display_ellipses));
3278
3279
3280 it->dp = window_display_table (w);
3281
3282
3283 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
3284
3285 it->tab_width = SANE_TAB_WIDTH (current_buffer);
3286
3287
3288 if (TRUNCATE != 0)
3289 it->line_wrap = TRUNCATE;
3290 if (base_face_id == DEFAULT_FACE_ID
3291 && !it->w->hscroll
3292 && (WINDOW_FULL_WIDTH_P (it->w)
3293 || NILP (Vtruncate_partial_width_windows)
3294 || (FIXNUMP (Vtruncate_partial_width_windows)
3295
3296 && (XFIXNUM (Vtruncate_partial_width_windows)
3297 <= WINDOW_TOTAL_COLS (it->w))))
3298 && NILP (BVAR (current_buffer, truncate_lines)))
3299 it->line_wrap = NILP (BVAR (current_buffer, word_wrap))
3300 ? WINDOW_WRAP : WORD_WRAP;
3301
3302
3303
3304
3305
3306
3307
3308 #ifdef HAVE_WINDOW_SYSTEM
3309 if (!(FRAME_WINDOW_P (it->f) && it->f->no_special_glyphs))
3310 #endif
3311 {
3312 if (it->line_wrap == TRUNCATE)
3313 {
3314
3315 eassert (it->glyph_row == NULL);
3316 produce_special_glyphs (it, IT_TRUNCATION);
3317 it->truncation_pixel_width = it->pixel_width;
3318 }
3319 else
3320 {
3321
3322 eassert (it->glyph_row == NULL);
3323 produce_special_glyphs (it, IT_CONTINUATION);
3324 it->continuation_pixel_width = it->pixel_width;
3325 }
3326 }
3327
3328
3329
3330 it->pixel_width = it->ascent = it->descent = 0;
3331 it->phys_ascent = it->phys_descent = 0;
3332
3333
3334
3335
3336 it->glyph_row = row;
3337 it->area = TEXT_AREA;
3338
3339
3340
3341
3342
3343 if (base_face_id != DEFAULT_FACE_ID)
3344 {
3345
3346 it->first_visible_x = 0;
3347 it->last_visible_x =
3348 WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
3349 }
3350 else
3351 {
3352
3353
3354
3355
3356
3357
3358 if (hscrolling_current_line_p (w))
3359 {
3360 if (w->min_hscroll > 0)
3361 it->first_visible_x = w->min_hscroll * FRAME_COLUMN_WIDTH (it->f);
3362 else
3363 it->first_visible_x = 0;
3364 }
3365 else
3366 it->first_visible_x =
3367 window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f);
3368
3369 body_width = window_box_width (w, TEXT_AREA);
3370 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3371 && body_width != w->old_body_pixel_width)
3372 FRAME_WINDOW_CHANGE (it->f) = true;
3373 it->last_visible_x = it->first_visible_x + body_width;
3374
3375
3376
3377
3378 if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
3379 {
3380 if (it->line_wrap == TRUNCATE)
3381 it->last_visible_x -= it->truncation_pixel_width;
3382 else
3383 it->last_visible_x -= it->continuation_pixel_width;
3384 }
3385
3386 it->tab_line_p = window_wants_tab_line (w);
3387 it->header_line_p = window_wants_header_line (w);
3388 body_height = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
3389 it->current_y = body_height + w->vscroll;
3390 }
3391
3392
3393 if (!FRAME_WINDOW_P (it->f)
3394 && !WINDOW_RIGHTMOST_P (it->w))
3395 it->last_visible_x -= 1;
3396
3397 it->last_visible_y = window_text_bottom_y (w);
3398 body_height += it->last_visible_y;
3399 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3400 && body_height != w->old_body_pixel_height)
3401 FRAME_WINDOW_CHANGE (it->f) = true;
3402
3403
3404
3405 if (base_face_id != DEFAULT_FACE_ID)
3406 {
3407 struct face *face;
3408
3409 it->face_id = remapped_base_face_id;
3410
3411
3412
3413 face = FACE_FROM_ID_OR_NULL (it->f, remapped_base_face_id);
3414 if (face && face->box != FACE_NO_BOX)
3415 {
3416 int box_thickness = face->box_vertical_line_width;
3417 it->face_box_p = true;
3418 it->start_of_box_run_p = true;
3419
3420
3421 if (box_thickness > 0)
3422 it->last_visible_x -= box_thickness;
3423 }
3424 }
3425
3426
3427
3428 if (charpos >= BUF_BEG (current_buffer))
3429 {
3430 it->stop_charpos = charpos;
3431 it->end_charpos = ZV;
3432 eassert (charpos == BYTE_TO_CHAR (bytepos));
3433 IT_CHARPOS (*it) = charpos;
3434 IT_BYTEPOS (*it) = bytepos;
3435
3436
3437
3438 it->face_id = it->base_face_id;
3439
3440 it->start = it->current;
3441
3442
3443
3444
3445
3446
3447
3448 it->bidi_p =
3449 !redisplay__inhibit_bidi
3450 && !NILP (BVAR (current_buffer, bidi_display_reordering))
3451 && it->multibyte_p;
3452
3453
3454
3455 if (it->bidi_p)
3456 {
3457
3458
3459
3460
3461 if (base_face_id == DEFAULT_FACE_ID
3462 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
3463 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
3464 {
3465 if (it->line_wrap == TRUNCATE)
3466 it->last_visible_x -= it->truncation_pixel_width;
3467 else
3468 it->last_visible_x -= it->continuation_pixel_width;
3469 }
3470
3471
3472 if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3473 Qleft_to_right))
3474 it->paragraph_embedding = L2R;
3475 else if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3476 Qright_to_left))
3477 it->paragraph_embedding = R2L;
3478 else
3479 it->paragraph_embedding = NEUTRAL_DIR;
3480 bidi_unshelve_cache (NULL, false);
3481 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
3482 &it->bidi_it);
3483 }
3484
3485
3486
3487 it->medium_narrowing_begv = 0;
3488
3489
3490 reseat (it, it->current.pos, true);
3491 }
3492
3493 CHECK_IT (it);
3494 }
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582 static int
3583 get_narrowed_width (struct window *w)
3584 {
3585
3586
3587 int fact = FRAME_WINDOW_P (XFRAME (w->frame)) ? 3 : 2;
3588
3589
3590
3591 int width = window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS)
3592 - ((WINDOW_RIGHT_FRINGE_WIDTH (w) == 0
3593 || WINDOW_LEFT_FRINGE_WIDTH (w) == 0) ? 1 : 0);
3594 return fact * max (1, width);
3595 }
3596
3597 static int
3598 get_narrowed_len (struct window *w)
3599 {
3600 int height = window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS);
3601 return get_narrowed_width (w) * max (1, height);
3602 }
3603
3604 static ptrdiff_t
3605 get_medium_narrowing_begv (struct window *w, ptrdiff_t pos)
3606 {
3607 int len = get_narrowed_len (w);
3608 return max ((pos / len - 1) * len, BEGV);
3609 }
3610
3611 static ptrdiff_t
3612 get_medium_narrowing_zv (struct window *w, ptrdiff_t pos)
3613 {
3614 int len = get_narrowed_len (w);
3615 return min ((pos / len + 1) * len, ZV);
3616 }
3617
3618
3619
3620
3621
3622
3623 static ptrdiff_t
3624 get_nearby_bol_pos (ptrdiff_t pos)
3625 {
3626 ptrdiff_t start, pos_bytepos, cur, next, found, bol = BEGV - 1, init_pos = pos;
3627 int dist;
3628 for (dist = 500; dist <= 500000; dist *= 10)
3629 {
3630 pos_bytepos = pos == BEGV ? BEGV_BYTE : CHAR_TO_BYTE (pos);
3631 start = pos - dist < BEGV ? BEGV : pos - dist;
3632 for (cur = start; cur < pos; cur = next)
3633 {
3634 next = find_newline1 (cur, CHAR_TO_BYTE (cur),
3635 pos, pos_bytepos,
3636 1, &found, NULL, false);
3637 if (found)
3638 bol = next;
3639 else
3640 break;
3641 }
3642 if (bol >= BEGV || start == BEGV)
3643 break;
3644 else
3645 pos = pos - dist < BEGV ? BEGV : pos - dist;
3646 }
3647 eassert (bol <= init_pos);
3648 return bol;
3649 }
3650
3651 ptrdiff_t
3652 get_small_narrowing_begv (struct window *w, ptrdiff_t pos)
3653 {
3654 int len = get_narrowed_width (w);
3655 ptrdiff_t bol_pos = max (get_nearby_bol_pos (pos), BEGV);
3656 return max (bol_pos + ((pos - bol_pos) / len - 1) * len, BEGV);
3657 }
3658
3659 ptrdiff_t
3660 get_large_narrowing_begv (ptrdiff_t pos)
3661 {
3662 if (long_line_optimizations_region_size <= 0)
3663 return BEGV;
3664 int len = long_line_optimizations_region_size / 2;
3665 int begv = max (pos - len, BEGV);
3666 int limit = long_line_optimizations_bol_search_limit;
3667 while (limit > 0)
3668 {
3669 if (begv == BEGV || FETCH_BYTE (CHAR_TO_BYTE (begv) - 1) == '\n')
3670 return begv;
3671 begv--;
3672 limit--;
3673 }
3674 return begv;
3675 }
3676
3677 ptrdiff_t
3678 get_large_narrowing_zv (ptrdiff_t pos)
3679 {
3680 if (long_line_optimizations_region_size <= 0)
3681 return ZV;
3682 int len = long_line_optimizations_region_size / 2;
3683 return min (pos + len, ZV);
3684 }
3685
3686 static void
3687 unwind_narrowed_begv (Lisp_Object point_min)
3688 {
3689 SET_BUF_BEGV (current_buffer, XFIXNUM (point_min));
3690 }
3691
3692
3693
3694
3695 #define SET_WITH_NARROWED_BEGV(IT,DST,EXPR,BV) \
3696 do { \
3697 if (IT->medium_narrowing_begv) \
3698 { \
3699 specpdl_ref count = SPECPDL_INDEX (); \
3700 record_unwind_protect (unwind_narrowed_begv, Fpoint_min ()); \
3701 SET_BUF_BEGV (current_buffer, BV); \
3702 DST = EXPR; \
3703 unbind_to (count, Qnil); \
3704 } \
3705 else \
3706 DST = EXPR; \
3707 } while (0)
3708
3709
3710
3711 void
3712 start_display (struct it *it, struct window *w, struct text_pos pos)
3713 {
3714 struct glyph_row *row;
3715 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
3716
3717 row = w->desired_matrix->rows + first_vpos;
3718 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
3719 it->first_vpos = first_vpos;
3720
3721
3722
3723 if (it->method == GET_FROM_BUFFER && it->line_wrap != TRUNCATE)
3724 {
3725 int first_y = it->current_y;
3726
3727
3728
3729 bool start_at_line_beg_p = (CHARPOS (pos) == BEGV
3730 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
3731 if (!start_at_line_beg_p)
3732 {
3733 int new_x;
3734
3735 reseat_at_previous_visible_line_start (it);
3736 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
3737
3738 new_x = it->current_x + it->pixel_width;
3739
3740
3741
3742
3743
3744
3745
3746 if (it->current_x > 0
3747 && it->line_wrap != TRUNCATE
3748 && (
3749 new_x > it->last_visible_x
3750
3751
3752 || (new_x == it->last_visible_x
3753 && FRAME_WINDOW_P (it->f)
3754 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
3755 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
3756 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
3757 {
3758 if ((it->current.dpvec_index >= 0
3759 || it->current.overlay_string_index >= 0)
3760
3761
3762
3763
3764
3765 && it->c != '\n')
3766 {
3767 set_iterator_to_next (it, true);
3768 move_it_in_display_line_to (it, -1, -1, 0);
3769 }
3770
3771 it->continuation_lines_width += it->current_x;
3772 }
3773
3774
3775
3776
3777
3778 else if (it->current.dpvec_index >= 0)
3779 it->current.dpvec_index = 0;
3780
3781
3782
3783
3784 it->max_ascent = it->max_descent = 0;
3785 it->max_phys_ascent = it->max_phys_descent = 0;
3786
3787 it->current_y = first_y;
3788 it->vpos = 0;
3789 it->current_x = it->hpos = 0;
3790 }
3791 }
3792 }
3793
3794
3795
3796
3797
3798 static bool
3799 in_ellipses_for_invisible_text_p (struct display_pos *pos, struct window *w)
3800 {
3801 Lisp_Object prop, window;
3802 bool ellipses_p = false;
3803 ptrdiff_t charpos = CHARPOS (pos->pos);
3804
3805
3806
3807
3808
3809 if (pos->dpvec_index >= 0
3810 && pos->overlay_string_index < 0
3811 && CHARPOS (pos->string_pos) < 0
3812 && charpos > BEGV
3813 && (XSETWINDOW (window, w),
3814 prop = Fget_char_property (make_fixnum (charpos),
3815 Qinvisible, window),
3816 TEXT_PROP_MEANS_INVISIBLE (prop) == 0))
3817 {
3818 prop = Fget_char_property (make_fixnum (charpos - 1), Qinvisible,
3819 window);
3820 ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
3821 }
3822
3823 return ellipses_p;
3824 }
3825
3826
3827
3828
3829
3830
3831
3832 static bool
3833 init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
3834 {
3835 ptrdiff_t charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
3836 int i;
3837 bool overlay_strings_with_newlines = false;
3838
3839
3840
3841
3842
3843 if (in_ellipses_for_invisible_text_p (pos, w))
3844 {
3845 --charpos;
3846 bytepos = 0;
3847 }
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858 init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
3859
3860
3861
3862
3863 for (i = 0; i < it->n_overlay_strings && i < OVERLAY_STRING_CHUNK_SIZE; ++i)
3864 {
3865 const char *s = SSDATA (it->overlay_strings[i]);
3866 const char *e = s + SBYTES (it->overlay_strings[i]);
3867
3868 while (s < e && *s != '\n')
3869 ++s;
3870
3871 if (s < e)
3872 {
3873 overlay_strings_with_newlines = true;
3874 break;
3875 }
3876 }
3877
3878
3879
3880 if (pos->overlay_string_index >= 0)
3881 {
3882 int relative_index;
3883
3884
3885
3886
3887
3888 if (it->method == GET_FROM_IMAGE)
3889 pop_it (it);
3890
3891
3892
3893
3894 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
3895 {
3896 ptrdiff_t n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
3897 it->current.overlay_string_index = 0;
3898 while (n--)
3899 {
3900 load_overlay_strings (it, 0);
3901 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
3902 }
3903 }
3904
3905 it->current.overlay_string_index = pos->overlay_string_index;
3906 relative_index = (it->current.overlay_string_index
3907 % OVERLAY_STRING_CHUNK_SIZE);
3908 it->string = it->overlay_strings[relative_index];
3909 eassert (STRINGP (it->string));
3910 it->current.string_pos = pos->string_pos;
3911 it->method = GET_FROM_STRING;
3912 it->end_charpos = SCHARS (it->string);
3913
3914 if (it->bidi_p)
3915 {
3916 it->bidi_it.string.lstring = it->string;
3917 it->bidi_it.string.s = NULL;
3918 it->bidi_it.string.schars = SCHARS (it->string);
3919 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
3920 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
3921 it->bidi_it.string.unibyte = !it->multibyte_p;
3922 it->bidi_it.w = it->w;
3923 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3924 FRAME_WINDOW_P (it->f), &it->bidi_it);
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934 if (CHARPOS (pos->string_pos) == 0)
3935 {
3936 get_visually_first_element (it);
3937 if (IT_STRING_CHARPOS (*it) != 0)
3938 do {
3939
3940 eassert (it->bidi_it.charpos < it->bidi_it.string.schars);
3941 bidi_move_to_visually_next (&it->bidi_it);
3942 } while (it->bidi_it.charpos != 0);
3943 }
3944 eassert (IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
3945 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos);
3946 }
3947 }
3948
3949 if (CHARPOS (pos->string_pos) >= 0)
3950 {
3951
3952
3953
3954 it->current.string_pos = pos->string_pos;
3955 eassert (STRINGP (it->string));
3956 if (it->bidi_p)
3957 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3958 FRAME_WINDOW_P (it->f), &it->bidi_it);
3959 }
3960
3961
3962
3963 if (pos->dpvec_index >= 0)
3964 {
3965 if (it->dpvec == NULL)
3966 get_next_display_element (it);
3967 eassert (it->dpvec && it->current.dpvec_index == 0);
3968 it->current.dpvec_index = pos->dpvec_index;
3969 }
3970
3971 CHECK_IT (it);
3972 return !overlay_strings_with_newlines;
3973 }
3974
3975
3976
3977
3978
3979 static void
3980 init_to_row_start (struct it *it, struct window *w, struct glyph_row *row)
3981 {
3982 init_from_display_pos (it, w, &row->start);
3983 it->start = row->start;
3984 it->continuation_lines_width = row->continuation_lines_width;
3985 CHECK_IT (it);
3986 }
3987
3988
3989
3990
3991
3992
3993
3994
3995 static bool
3996 init_to_row_end (struct it *it, struct window *w, struct glyph_row *row)
3997 {
3998 bool success = false;
3999
4000 if (init_from_display_pos (it, w, &row->end))
4001 {
4002 if (row->continued_p)
4003 it->continuation_lines_width
4004 = row->continuation_lines_width + row->pixel_width;
4005 CHECK_IT (it);
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015 if (get_next_display_element (it)
4016 && (it->bidi_it.scan_dir == -1 && it->cmp_it.id >= 0))
4017 success = false;
4018 else
4019 success = true;
4020 }
4021
4022 return success;
4023 }
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036 static void
4037 handle_stop (struct it *it)
4038 {
4039 enum prop_handled handled;
4040 bool handle_overlay_change_p;
4041 struct props *p;
4042
4043 it->dpvec = NULL;
4044 it->current.dpvec_index = -1;
4045 handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p;
4046 it->ellipsis_p = false;
4047
4048
4049 if (it->selective_display_ellipsis_p)
4050 it->saved_face_id = it->face_id;
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094 do
4095 {
4096 handled = HANDLED_NORMALLY;
4097
4098
4099 for (p = it_props; p->handler; ++p)
4100 {
4101 handled = p->handler (it);
4102
4103 if (handled == HANDLED_RECOMPUTE_PROPS)
4104 break;
4105 else if (handled == HANDLED_RETURN)
4106 {
4107
4108
4109 if (!handle_overlay_change_p
4110 || it->sp > 1
4111
4112
4113
4114
4115
4116
4117 || (it->current.overlay_string_index < 0
4118 && !get_overlay_strings_1 (it, 0, false)))
4119 {
4120 if (it->ellipsis_p)
4121 setup_for_ellipsis (it, 0);
4122
4123
4124
4125
4126
4127 if (STRINGP (it->string) && !SCHARS (it->string))
4128 pop_it (it);
4129 return;
4130 }
4131 else if (STRINGP (it->string) && !SCHARS (it->string))
4132 pop_it (it);
4133 else
4134 {
4135 it->string_from_display_prop_p = false;
4136 it->from_disp_prop_p = false;
4137 handle_overlay_change_p = false;
4138 }
4139 handled = HANDLED_RECOMPUTE_PROPS;
4140 break;
4141 }
4142 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
4143 handle_overlay_change_p = false;
4144 }
4145
4146 if (handled != HANDLED_RECOMPUTE_PROPS)
4147 {
4148
4149
4150 if (it->method == GET_FROM_DISPLAY_VECTOR)
4151 handle_overlay_change_p = false;
4152
4153
4154
4155
4156 if (handle_overlay_change_p)
4157 handled = handle_overlay_change (it);
4158 }
4159
4160 if (it->ellipsis_p)
4161 {
4162 setup_for_ellipsis (it, 0);
4163 break;
4164 }
4165 }
4166 while (handled == HANDLED_RECOMPUTE_PROPS);
4167
4168
4169 if (handled == HANDLED_NORMALLY)
4170 compute_stop_pos (it);
4171 }
4172
4173
4174
4175
4176
4177 static void
4178 compute_stop_pos (struct it *it)
4179 {
4180 register INTERVAL iv, next_iv;
4181 Lisp_Object object, limit, position;
4182 ptrdiff_t charpos, bytepos;
4183
4184 if (STRINGP (it->string))
4185 {
4186
4187
4188 it->stop_charpos = it->end_charpos;
4189 object = it->string;
4190 limit = Qnil;
4191 charpos = IT_STRING_CHARPOS (*it);
4192 bytepos = IT_STRING_BYTEPOS (*it);
4193 }
4194 else
4195 {
4196 ptrdiff_t pos;
4197
4198
4199
4200 if (it->end_charpos > ZV)
4201 it->end_charpos = ZV;
4202 it->stop_charpos = it->end_charpos;
4203
4204
4205
4206
4207
4208 charpos = IT_CHARPOS (*it);
4209 bytepos = IT_BYTEPOS (*it);
4210 pos = next_overlay_change (charpos);
4211 if (pos < it->stop_charpos)
4212 it->stop_charpos = pos;
4213
4214 if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
4215 && !NILP (Vauto_composition_mode)
4216 && composition_break_at_point
4217 && charpos < PT && PT < it->stop_charpos)
4218 it->stop_charpos = PT;
4219
4220
4221
4222 XSETBUFFER (object, current_buffer);
4223 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4224
4225
4226
4227
4228
4229
4230 if (!composition_break_at_point
4231 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
4232 && !NILP (Vauto_composition_mode))
4233 {
4234 ptrdiff_t endpos = charpos + 10 * TEXT_PROP_DISTANCE_LIMIT;
4235 bool found = false;
4236
4237 if (pos > ZV)
4238 pos = ZV;
4239 if (endpos > ZV)
4240 endpos = ZV;
4241 ptrdiff_t bpos = CHAR_TO_BYTE (pos);
4242 while (pos < endpos)
4243 {
4244 int ch = fetch_char_advance_no_check (&pos, &bpos);
4245 if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\f')
4246 {
4247 found = true;
4248 break;
4249 }
4250 }
4251 if (found)
4252 pos--;
4253 else if (it->stop_charpos < endpos)
4254 pos = it->stop_charpos;
4255 else
4256 {
4257
4258 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4259 }
4260 }
4261 limit = make_fixnum (pos);
4262 }
4263
4264
4265
4266 position = make_fixnum (charpos);
4267 iv = validate_interval_range (object, &position, &position, false);
4268 if (iv)
4269 {
4270 Lisp_Object values_here[LAST_PROP_IDX];
4271 struct props *p;
4272
4273
4274 for (p = it_props; p->handler; ++p)
4275 values_here[p->idx] = textget (iv->plist,
4276 builtin_lisp_symbol (p->name));
4277
4278
4279
4280 for (next_iv = next_interval (iv);
4281 (next_iv
4282 && (NILP (limit)
4283 || XFIXNAT (limit) > next_iv->position));
4284 next_iv = next_interval (next_iv))
4285 {
4286 for (p = it_props; p->handler; ++p)
4287 {
4288 Lisp_Object new_value = textget (next_iv->plist,
4289 builtin_lisp_symbol (p->name));
4290 if (!EQ (values_here[p->idx], new_value))
4291 break;
4292 }
4293
4294 if (p->handler)
4295 break;
4296 }
4297
4298 if (next_iv)
4299 {
4300 if (FIXNUMP (limit)
4301 && next_iv->position >= XFIXNAT (limit))
4302
4303 it->stop_charpos = min (XFIXNAT (limit), it->stop_charpos);
4304 else
4305
4306 it->stop_charpos = min (it->stop_charpos, next_iv->position);
4307 }
4308 }
4309
4310 if (it->cmp_it.id < 0)
4311 {
4312 ptrdiff_t stoppos = it->end_charpos;
4313
4314 if (it->bidi_p && it->bidi_it.scan_dir < 0)
4315 stoppos = -1;
4316 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos,
4317 stoppos, it->string);
4318 }
4319
4320 eassert (STRINGP (it->string)
4321 || (it->stop_charpos >= BEGV
4322 && it->stop_charpos >= IT_CHARPOS (*it)));
4323 }
4324
4325
4326
4327
4328 #define MAX_DISP_SCAN 250
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342 ptrdiff_t
4343 compute_display_string_pos (struct text_pos *position,
4344 struct bidi_string_data *string,
4345 struct window *w,
4346 bool frame_window_p, int *disp_prop)
4347 {
4348
4349 Lisp_Object object, object1;
4350 Lisp_Object pos, spec, limpos;
4351 bool string_p = string && (STRINGP (string->lstring) || string->s);
4352 ptrdiff_t eob = string_p ? string->schars : ZV;
4353 ptrdiff_t begb = string_p ? 0 : BEGV;
4354 ptrdiff_t bufpos, charpos = CHARPOS (*position);
4355 ptrdiff_t lim =
4356 (charpos < eob - MAX_DISP_SCAN) ? charpos + MAX_DISP_SCAN : eob;
4357 struct text_pos tpos;
4358 int rv = 0;
4359
4360 if (string && STRINGP (string->lstring))
4361 object1 = object = string->lstring;
4362 else if (w && !string_p)
4363 {
4364 XSETWINDOW (object, w);
4365 object1 = Qnil;
4366 }
4367 else
4368 object1 = object = Qnil;
4369
4370 *disp_prop = 1;
4371
4372 if (charpos >= eob
4373
4374
4375 || string->from_disp_str
4376
4377 || (string->s && !STRINGP (object)))
4378 {
4379 *disp_prop = 0;
4380 return eob;
4381 }
4382
4383
4384
4385 pos = make_fixnum (charpos);
4386 if (STRINGP (object))
4387 bufpos = string->bufpos;
4388 else
4389 bufpos = charpos;
4390 tpos = *position;
4391 if (!NILP (spec = Fget_char_property (pos, Qdisplay, object))
4392 && (charpos <= begb
4393 || !EQ (Fget_char_property (make_fixnum (charpos - 1), Qdisplay,
4394 object),
4395 spec))
4396 && (rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos, bufpos,
4397 frame_window_p)))
4398 {
4399 if (rv == 2)
4400 *disp_prop = 2;
4401 return charpos;
4402 }
4403
4404
4405
4406 limpos = make_fixnum (lim);
4407 do {
4408 pos = Fnext_single_char_property_change (pos, Qdisplay, object1, limpos);
4409 CHARPOS (tpos) = XFIXNAT (pos);
4410 if (CHARPOS (tpos) >= lim)
4411 {
4412 *disp_prop = 0;
4413 break;
4414 }
4415 if (STRINGP (object))
4416 BYTEPOS (tpos) = string_char_to_byte (object, CHARPOS (tpos));
4417 else
4418 BYTEPOS (tpos) = CHAR_TO_BYTE (CHARPOS (tpos));
4419 spec = Fget_char_property (pos, Qdisplay, object);
4420 if (!STRINGP (object))
4421 bufpos = CHARPOS (tpos);
4422 } while (NILP (spec)
4423 || !(rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos,
4424 bufpos, frame_window_p)));
4425 if (rv == 2)
4426 *disp_prop = 2;
4427
4428 return CHARPOS (tpos);
4429 }
4430
4431
4432
4433
4434
4435
4436 ptrdiff_t
4437 compute_display_string_end (ptrdiff_t charpos, struct bidi_string_data *string)
4438 {
4439
4440 Lisp_Object object =
4441 (string && STRINGP (string->lstring)) ? string->lstring : Qnil;
4442 Lisp_Object pos = make_fixnum (charpos);
4443 ptrdiff_t eob =
4444 (STRINGP (object) || (string && string->s)) ? string->schars : ZV;
4445
4446 if (charpos >= eob || (string->s && !STRINGP (object)))
4447 return eob;
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463 if (NILP (Fget_char_property (pos, Qdisplay, object)))
4464 return -1;
4465
4466
4467
4468 pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil);
4469
4470 return XFIXNAT (pos);
4471 }
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483 static enum prop_handled
4484 handle_fontified_prop (struct it *it)
4485 {
4486 Lisp_Object prop, pos;
4487 enum prop_handled handled = HANDLED_NORMALLY;
4488
4489 if (!NILP (Vmemory_full))
4490 return handled;
4491
4492
4493
4494
4495
4496 if (!STRINGP (it->string)
4497 && it->s == NULL
4498 && !NILP (Vfontification_functions)
4499 && !(input_was_pending && redisplay_skip_fontification_on_input)
4500 && !NILP (Vrun_hooks)
4501 && (pos = make_fixnum (IT_CHARPOS (*it)),
4502 prop = Fget_char_property (pos, Qfontified, Qnil),
4503
4504
4505 NILP (prop) && IT_CHARPOS (*it) < Z))
4506 {
4507 specpdl_ref count = SPECPDL_INDEX ();
4508 Lisp_Object val;
4509 struct buffer *obuf = current_buffer;
4510 ptrdiff_t begv = BEGV, zv = ZV;
4511 bool old_clip_changed = current_buffer->clip_changed;
4512 bool saved_inhibit_flag = it->f->inhibit_clear_image_cache;
4513
4514 val = Vfontification_functions;
4515 specbind (Qfontification_functions, Qnil);
4516
4517 eassert (it->end_charpos == ZV);
4518
4519 if (current_buffer->long_line_optimizations_p
4520 && long_line_optimizations_region_size > 0)
4521 {
4522 ptrdiff_t begv = it->large_narrowing_begv;
4523 ptrdiff_t zv = it->large_narrowing_zv;
4524 ptrdiff_t charpos = IT_CHARPOS (*it);
4525 if (charpos < begv || charpos > zv)
4526 {
4527 begv = get_large_narrowing_begv (charpos);
4528 zv = get_large_narrowing_zv (charpos);
4529 }
4530 if (begv != BEG || zv != Z)
4531 labeled_narrow_to_region (make_fixnum (begv), make_fixnum (zv),
4532 Qlong_line_optimizations_in_fontification_functions);
4533 }
4534
4535
4536
4537 it->f->inhibit_clear_image_cache = true;
4538
4539 if (!CONSP (val) || EQ (XCAR (val), Qlambda))
4540 safe_call1 (val, pos);
4541 else
4542 {
4543 Lisp_Object fns, fn;
4544
4545 fns = Qnil;
4546
4547 for (; CONSP (val); val = XCDR (val))
4548 {
4549 fn = XCAR (val);
4550
4551 if (EQ (fn, Qt))
4552 {
4553
4554
4555
4556
4557
4558 for (fns = Fdefault_value (Qfontification_functions);
4559 CONSP (fns);
4560 fns = XCDR (fns))
4561 {
4562 fn = XCAR (fns);
4563 if (!EQ (fn, Qt))
4564 safe_call1 (fn, pos);
4565 }
4566 }
4567 else
4568 safe_call1 (fn, pos);
4569 }
4570 }
4571
4572 it->f->inhibit_clear_image_cache = saved_inhibit_flag;
4573 unbind_to (count, Qnil);
4574
4575
4576
4577
4578
4579
4580
4581
4582 if (obuf == current_buffer)
4583 {
4584 if (begv == BEGV && zv == ZV)
4585 current_buffer->clip_changed = old_clip_changed;
4586 }
4587
4588
4589 else if (BUFFER_LIVE_P (obuf))
4590 set_buffer_internal_1 (obuf);
4591
4592
4593
4594
4595
4596
4597 it->end_charpos = ZV;
4598
4599
4600
4601
4602 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
4603 handled = HANDLED_RECOMPUTE_PROPS;
4604 }
4605
4606 return handled;
4607 }
4608
4609
4610
4611
4612
4613
4614
4615 static int
4616 face_at_pos (const struct it *it, enum lface_attribute_index attr_filter)
4617 {
4618 ptrdiff_t next_stop;
4619
4620 if (!STRINGP (it->string))
4621 {
4622 return face_at_buffer_position (it->w,
4623 IT_CHARPOS (*it),
4624 &next_stop,
4625 (IT_CHARPOS (*it)
4626 + TEXT_PROP_DISTANCE_LIMIT),
4627 false, it->base_face_id,
4628 attr_filter);
4629 }
4630 else
4631 {
4632 int base_face_id;
4633 ptrdiff_t bufpos;
4634 int i;
4635 Lisp_Object from_overlay
4636 = (it->current.overlay_string_index >= 0
4637 ? it->string_overlays[it->current.overlay_string_index
4638 % OVERLAY_STRING_CHUNK_SIZE]
4639 : Qnil);
4640
4641
4642
4643
4644
4645
4646
4647 if (! NILP (from_overlay))
4648 for (i = it->sp - 1; i >= 0; i--)
4649 {
4650 if (it->stack[i].current.overlay_string_index >= 0)
4651 from_overlay
4652 = it->string_overlays[it->stack[i].current.overlay_string_index
4653 % OVERLAY_STRING_CHUNK_SIZE];
4654 else if (! NILP (it->stack[i].from_overlay))
4655 from_overlay = it->stack[i].from_overlay;
4656
4657 if (!NILP (from_overlay))
4658 break;
4659 }
4660
4661 if (! NILP (from_overlay))
4662 {
4663 bufpos = IT_CHARPOS (*it);
4664
4665
4666 base_face_id
4667 = face_for_overlay_string (it->w,
4668 IT_CHARPOS (*it),
4669 &next_stop,
4670 (IT_CHARPOS (*it)
4671 + TEXT_PROP_DISTANCE_LIMIT),
4672 false,
4673 from_overlay, attr_filter);
4674 }
4675 else
4676 {
4677 bufpos = 0;
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695 base_face_id = it->string_from_prefix_prop_p
4696 ? (!NILP (Vface_remapping_alist)
4697 ? lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
4698 : DEFAULT_FACE_ID)
4699 : underlying_face_id (it);
4700 }
4701
4702 return face_at_string_position (it->w,
4703 it->string,
4704 IT_STRING_CHARPOS (*it),
4705 bufpos,
4706 &next_stop,
4707 base_face_id, false,
4708 attr_filter);
4709 }
4710 }
4711
4712
4713
4714
4715 static enum prop_handled
4716 handle_face_prop (struct it *it)
4717 {
4718 specpdl_ref count = SPECPDL_INDEX ();
4719
4720
4721
4722 specbind (Qinhibit_quit, Qt);
4723 const int new_face_id = face_at_pos (it, 0);
4724 unbind_to (count, Qnil);
4725
4726
4727
4728
4729
4730
4731
4732
4733 if (new_face_id != it->face_id)
4734 {
4735 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
4736
4737
4738
4739 struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
4740
4741
4742
4743
4744 if (!STRINGP (it->string)
4745 && !old_face
4746 && IT_CHARPOS (*it) > BEG)
4747 {
4748 const int prev_face_id = face_before_it_pos (it);
4749
4750 old_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
4751 }
4752
4753
4754
4755
4756 it->face_id = new_face_id;
4757
4758
4759 if (!(it->start_of_box_run_p && old_face && old_face->box))
4760 it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
4761 && (old_face == NULL || !old_face->box));
4762 it->face_box_p = new_face->box != FACE_NO_BOX;
4763 }
4764
4765 return HANDLED_NORMALLY;
4766 }
4767
4768
4769
4770
4771
4772
4773
4774 static int
4775 underlying_face_id (const struct it *it)
4776 {
4777 int face_id = it->base_face_id, i;
4778
4779 eassert (STRINGP (it->string));
4780
4781 for (i = it->sp - 1; i >= 0; --i)
4782 if (NILP (it->stack[i].string))
4783 face_id = it->stack[i].face_id;
4784
4785 return face_id;
4786 }
4787
4788
4789
4790
4791
4792
4793
4794 static int
4795 face_before_or_after_it_pos (struct it *it, bool before_p)
4796 {
4797 int face_id, limit;
4798 ptrdiff_t next_check_charpos;
4799 struct it it_copy;
4800 void *it_copy_data = NULL;
4801
4802 eassert (it->s == NULL);
4803
4804 if (STRINGP (it->string))
4805 {
4806 ptrdiff_t bufpos, charpos;
4807 int base_face_id;
4808
4809
4810
4811
4812
4813 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
4814 || (IT_STRING_CHARPOS (*it) == 0 && before_p)
4815 || it->current_x <= it->first_visible_x)
4816 return it->face_id;
4817
4818 if (!it->bidi_p)
4819 {
4820
4821
4822
4823 if (before_p)
4824 charpos = IT_STRING_CHARPOS (*it) - 1;
4825 else if (it->what == IT_COMPOSITION)
4826
4827
4828 charpos = IT_STRING_CHARPOS (*it) + it->cmp_it.nchars;
4829 else
4830 charpos = IT_STRING_CHARPOS (*it) + 1;
4831 }
4832 else
4833 {
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844 SAVE_IT (it_copy, *it, it_copy_data);
4845 IT_STRING_CHARPOS (it_copy) = 0;
4846 bidi_init_it (0, 0, FRAME_WINDOW_P (it_copy.f), &it_copy.bidi_it);
4847 it_copy.bidi_it.scan_dir = 0;
4848
4849 do
4850 {
4851 charpos = it_copy.bidi_it.charpos;
4852 if (charpos >= SCHARS (it->string))
4853 break;
4854 bidi_move_to_visually_next (&it_copy.bidi_it);
4855 }
4856 while (it_copy.bidi_it.charpos != IT_STRING_CHARPOS (*it));
4857
4858 if (!before_p)
4859 {
4860
4861
4862
4863 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4864
4865
4866
4867 if (it_copy.bidi_it.first_elt)
4868 n++;
4869 while (n--)
4870 bidi_move_to_visually_next (&it_copy.bidi_it);
4871
4872 charpos = it_copy.bidi_it.charpos;
4873 }
4874
4875 RESTORE_IT (it, it, it_copy_data);
4876 }
4877 eassert (0 <= charpos && charpos <= SCHARS (it->string));
4878
4879 if (it->current.overlay_string_index >= 0)
4880 bufpos = IT_CHARPOS (*it);
4881 else
4882 bufpos = 0;
4883
4884 base_face_id = underlying_face_id (it);
4885
4886
4887 face_id = face_at_string_position (it->w, it->string, charpos,
4888 bufpos, &next_check_charpos,
4889 base_face_id, false, 0);
4890
4891
4892
4893
4894 if (STRING_MULTIBYTE (it->string))
4895 {
4896 struct text_pos pos1 = string_pos (charpos, it->string);
4897 const unsigned char *p = SDATA (it->string) + BYTEPOS (pos1);
4898 struct face *face = FACE_FROM_ID (it->f, face_id);
4899 int len, c = check_char_and_length (p, &len);
4900 face_id = FACE_FOR_CHAR (it->f, face, c, charpos, it->string);
4901 }
4902 }
4903 else
4904 {
4905 struct text_pos pos;
4906
4907 if ((IT_CHARPOS (*it) >= ZV && !before_p)
4908 || (IT_CHARPOS (*it) <= BEGV && before_p))
4909 return it->face_id;
4910
4911 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
4912 pos = it->current.pos;
4913
4914 if (!it->bidi_p)
4915 {
4916 if (before_p)
4917 DEC_TEXT_POS (pos, it->multibyte_p);
4918 else
4919 {
4920 if (it->what == IT_COMPOSITION)
4921 {
4922
4923
4924 pos.charpos += it->cmp_it.nchars;
4925 pos.bytepos += it->len;
4926 }
4927 else
4928 INC_TEXT_POS (pos, it->multibyte_p);
4929 }
4930 }
4931 else
4932 {
4933 if (before_p)
4934 {
4935 int current_x;
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946 if (it->current_x <= it->first_visible_x)
4947 return it->face_id;
4948 SAVE_IT (it_copy, *it, it_copy_data);
4949
4950
4951
4952
4953
4954 current_x = it_copy.current_x;
4955 move_it_vertically_backward (&it_copy, 0);
4956 move_it_in_display_line (&it_copy, ZV, current_x - 1, MOVE_TO_X);
4957 pos = it_copy.current.pos;
4958 RESTORE_IT (it, it, it_copy_data);
4959 }
4960 else
4961 {
4962
4963
4964
4965 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4966
4967 it_copy = *it;
4968
4969
4970
4971 if (it->bidi_it.first_elt)
4972 n++;
4973 while (n--)
4974 bidi_move_to_visually_next (&it_copy.bidi_it);
4975
4976 SET_TEXT_POS (pos,
4977 it_copy.bidi_it.charpos, it_copy.bidi_it.bytepos);
4978 }
4979 }
4980 eassert (BEGV <= CHARPOS (pos) && CHARPOS (pos) <= ZV);
4981
4982
4983 face_id = face_at_buffer_position (it->w,
4984 CHARPOS (pos),
4985 &next_check_charpos,
4986 limit, false, -1, 0);
4987
4988
4989
4990
4991 if (it->multibyte_p)
4992 {
4993 int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
4994 struct face *face = FACE_FROM_ID (it->f, face_id);
4995 face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), Qnil);
4996 }
4997 }
4998
4999 return face_id;
5000 }
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011 static enum prop_handled
5012 handle_invisible_prop (struct it *it)
5013 {
5014 enum prop_handled handled = HANDLED_NORMALLY;
5015 int invis;
5016 Lisp_Object prop;
5017
5018 if (STRINGP (it->string))
5019 {
5020 Lisp_Object end_charpos, limit;
5021
5022
5023
5024
5025 end_charpos = make_fixnum (IT_STRING_CHARPOS (*it));
5026 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5027 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5028
5029 if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5030 {
5031
5032
5033 bool display_ellipsis_p = (invis == 2);
5034 ptrdiff_t len, endpos;
5035
5036 handled = HANDLED_RECOMPUTE_PROPS;
5037
5038
5039
5040 endpos = len = SCHARS (it->string);
5041 XSETINT (limit, len);
5042 do
5043 {
5044 end_charpos
5045 = Fnext_single_property_change (end_charpos, Qinvisible,
5046 it->string, limit);
5047
5048
5049 eassert (FIXNUMP (end_charpos));
5050 if (FIXNUMP (end_charpos))
5051 {
5052 endpos = XFIXNAT (end_charpos);
5053 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5054 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5055 if (invis == 2)
5056 display_ellipsis_p = true;
5057 }
5058 else
5059 endpos = len;
5060 }
5061 while (invis != 0 && endpos < len);
5062
5063 if (display_ellipsis_p)
5064 it->ellipsis_p = true;
5065
5066 if (endpos < len)
5067 {
5068
5069 struct text_pos old;
5070 ptrdiff_t oldpos;
5071
5072 old = it->current.string_pos;
5073 oldpos = CHARPOS (old);
5074 if (it->bidi_p)
5075 {
5076 if (it->bidi_it.first_elt
5077 && it->bidi_it.charpos < SCHARS (it->string))
5078 bidi_paragraph_init (it->paragraph_embedding,
5079 &it->bidi_it, true);
5080
5081 do
5082 {
5083 bidi_move_to_visually_next (&it->bidi_it);
5084 }
5085 while (oldpos <= it->bidi_it.charpos
5086 && it->bidi_it.charpos < endpos
5087 && it->bidi_it.charpos < it->bidi_it.string.schars);
5088
5089 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
5090 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
5091 if (IT_CHARPOS (*it) >= endpos)
5092 it->prev_stop = endpos;
5093 }
5094 else
5095 {
5096 IT_STRING_CHARPOS (*it) = endpos;
5097 compute_string_pos (&it->current.string_pos, old, it->string);
5098 }
5099 }
5100 else
5101 {
5102
5103
5104
5105 if (it->current.overlay_string_index >= 0
5106 && !display_ellipsis_p)
5107 {
5108 next_overlay_string (it);
5109
5110
5111 handled = HANDLED_OVERLAY_STRING_CONSUMED;
5112 }
5113 else
5114 {
5115 IT_STRING_CHARPOS (*it) = SCHARS (it->string);
5116 IT_STRING_BYTEPOS (*it) = SBYTES (it->string);
5117 }
5118 }
5119 }
5120 }
5121 else
5122 {
5123 ptrdiff_t newpos, next_stop, start_charpos, tem;
5124 Lisp_Object pos, overlay;
5125
5126
5127 tem = start_charpos = IT_CHARPOS (*it);
5128 pos = make_fixnum (tem);
5129 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
5130 &overlay);
5131 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5132
5133
5134 if (invis != 0 && start_charpos < it->end_charpos)
5135 {
5136
5137
5138 bool display_ellipsis_p = invis == 2;
5139
5140 handled = HANDLED_RECOMPUTE_PROPS;
5141
5142
5143
5144 do
5145 {
5146
5147
5148
5149
5150
5151 newpos = skip_invisible (tem, &next_stop, ZV, it->window);
5152
5153
5154
5155
5156 if (newpos == tem || newpos >= ZV)
5157 invis = 0;
5158 else
5159 {
5160
5161
5162
5163
5164
5165
5166 pos = make_fixnum (newpos);
5167 prop = Fget_char_property (pos, Qinvisible, it->window);
5168 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5169 }
5170
5171
5172
5173 if (invis != 0)
5174 tem = next_stop;
5175
5176
5177
5178 if (invis == 2)
5179 display_ellipsis_p = true;
5180 }
5181 while (invis != 0);
5182
5183
5184 if (it->bidi_p)
5185 {
5186 ptrdiff_t bpos = CHAR_TO_BYTE (newpos);
5187 bool on_newline
5188 = bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
5189 bool after_newline
5190 = newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
5191
5192
5193
5194
5195
5196
5197
5198
5199 if (on_newline || after_newline)
5200 {
5201 struct text_pos tpos;
5202 bidi_dir_t pdir = it->bidi_it.paragraph_dir;
5203
5204 SET_TEXT_POS (tpos, newpos, bpos);
5205 reseat_1 (it, tpos, false);
5206
5207
5208
5209
5210
5211 if (on_newline)
5212 {
5213 it->bidi_it.first_elt = false;
5214 it->bidi_it.paragraph_dir = pdir;
5215 it->bidi_it.ch = (bpos == ZV_BYTE) ? -1 : '\n';
5216 it->bidi_it.nchars = 1;
5217 it->bidi_it.ch_len = 1;
5218 }
5219 }
5220 else
5221 {
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
5233 {
5234
5235
5236
5237
5238
5239
5240
5241 bidi_paragraph_init (it->paragraph_embedding,
5242 &it->bidi_it, true);
5243 }
5244 do
5245 {
5246 bidi_move_to_visually_next (&it->bidi_it);
5247 }
5248 while (it->stop_charpos <= it->bidi_it.charpos
5249 && it->bidi_it.charpos < newpos);
5250 IT_CHARPOS (*it) = it->bidi_it.charpos;
5251 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
5252
5253
5254
5255
5256 if (IT_CHARPOS (*it) >= newpos)
5257 it->prev_stop = newpos;
5258 }
5259 }
5260 else
5261 {
5262 IT_CHARPOS (*it) = newpos;
5263 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
5264 }
5265
5266 if (display_ellipsis_p)
5267 {
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280 if (!STRINGP (it->object))
5281 {
5282 it->position.charpos = newpos - 1;
5283 it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
5284 }
5285 }
5286
5287
5288
5289
5290
5291
5292
5293 if (NILP (overlay)
5294 && get_overlay_strings (it, it->stop_charpos))
5295 {
5296 handled = HANDLED_RECOMPUTE_PROPS;
5297 if (it->sp > 0)
5298 {
5299 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312 it->stack[it->sp - 1].stop_charpos
5313 = CHARPOS (it->stack[it->sp - 1].current.pos);
5314 }
5315 }
5316 else if (display_ellipsis_p)
5317 {
5318 it->ellipsis_p = true;
5319
5320
5321
5322 handled = HANDLED_RETURN;
5323 }
5324 }
5325 }
5326
5327 return handled;
5328 }
5329
5330
5331
5332
5333
5334 static void
5335 setup_for_ellipsis (struct it *it, int len)
5336 {
5337
5338
5339 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
5340 {
5341 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
5342 it->dpvec = v->contents;
5343 it->dpend = v->contents + v->header.size;
5344 }
5345 else
5346 {
5347
5348 it->dpvec = default_invis_vector;
5349 it->dpend = default_invis_vector + 3;
5350 }
5351
5352 it->dpvec_char_len = len;
5353 it->current.dpvec_index = 0;
5354 it->dpvec_face_id = -1;
5355
5356
5357
5358
5359
5360
5361
5362
5363 if (it->saved_face_id >= 0)
5364 it->face_id = it->saved_face_id;
5365
5366
5367
5368 if (it->method == GET_FROM_BUFFER)
5369 it->ignore_overlay_strings_at_pos_p = false;
5370
5371 it->method = GET_FROM_DISPLAY_VECTOR;
5372 it->ellipsis_p = true;
5373 }
5374
5375
5376 static Lisp_Object
5377 find_display_property (Lisp_Object disp, Lisp_Object prop)
5378 {
5379 if (NILP (disp))
5380 return Qnil;
5381
5382 if (VECTORP (disp))
5383 {
5384 for (ptrdiff_t i = 0; i < ASIZE (disp); i++)
5385 {
5386 Lisp_Object elem = AREF (disp, i);
5387 if (CONSP (elem)
5388 && CONSP (XCDR (elem))
5389 && EQ (XCAR (elem), prop))
5390 return XCAR (XCDR (elem));
5391 }
5392 return Qnil;
5393 }
5394
5395 else if (CONSP (disp)
5396 && CONSP (XCAR (disp)))
5397 {
5398 while (!NILP (disp))
5399 {
5400 Lisp_Object elem = XCAR (disp);
5401 if (CONSP (elem)
5402 && CONSP (XCDR (elem))
5403 && EQ (XCAR (elem), prop))
5404 return XCAR (XCDR (elem));
5405
5406
5407
5408 if (CONSP (XCDR (disp)))
5409 disp = XCDR (disp);
5410 else
5411 disp = Qnil;
5412 }
5413 return Qnil;
5414 }
5415
5416 else if (CONSP (disp)
5417 && CONSP (XCDR (disp))
5418 && EQ (XCAR (disp), prop))
5419 return XCAR (XCDR (disp));
5420 else
5421 return Qnil;
5422 }
5423
5424 static Lisp_Object
5425 get_display_property (ptrdiff_t bufpos, Lisp_Object prop, Lisp_Object object)
5426 {
5427 return find_display_property (Fget_text_property (make_fixnum (bufpos),
5428 Qdisplay, object),
5429 prop);
5430 }
5431
5432 static void
5433 display_min_width (struct it *it, ptrdiff_t bufpos,
5434 Lisp_Object object, Lisp_Object width_spec)
5435 {
5436
5437
5438 if (!NILP (it->min_width_property)
5439 && !EQ (width_spec, it->min_width_property))
5440 {
5441 if (!it->glyph_row)
5442 return;
5443
5444
5445
5446
5447
5448 if ((bufpos == 0
5449 && !EQ (it->min_width_property,
5450 get_display_property (0, Qmin_width, object)))
5451
5452
5453 || (bufpos > BEGV
5454 && EQ (it->min_width_property,
5455 get_display_property (bufpos - 1, Qmin_width, object))))
5456 {
5457 Lisp_Object w = Qnil;
5458 double width;
5459 #ifdef HAVE_WINDOW_SYSTEM
5460 if (FRAME_WINDOW_P (it->f))
5461 {
5462 struct font *font = NULL;
5463 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5464 font = face->font ? face->font : FRAME_FONT (it->f);
5465 calc_pixel_width_or_height (&width, it,
5466 XCAR (it->min_width_property),
5467 font, true, NULL);
5468 width -= it->current_x - it->min_width_start;
5469 w = list1 (make_int (width));
5470 }
5471 else
5472 #endif
5473 {
5474 calc_pixel_width_or_height (&width, it,
5475 XCAR (it->min_width_property),
5476 NULL, true, NULL);
5477 width -= (it->current_x - it->min_width_start) /
5478 FRAME_COLUMN_WIDTH (it->f);
5479 w = make_int (width);
5480 }
5481
5482
5483 it->object = list3 (Qspace, QCwidth, w);
5484 produce_stretch_glyph (it);
5485 if (it->area == TEXT_AREA)
5486 it->current_x += it->pixel_width;
5487 it->min_width_property = Qnil;
5488 }
5489 }
5490
5491
5492
5493
5494 if (CONSP (width_spec))
5495 {
5496 if (bufpos == BEGV
5497
5498 || (bufpos == 0
5499 && !EQ (it->min_width_property,
5500 get_display_property (0, Qmin_width, object)))
5501
5502 || (bufpos > BEGV
5503 && !EQ (width_spec,
5504 get_display_property (bufpos - 1, Qmin_width, object))))
5505 {
5506 it->min_width_property = width_spec;
5507 it->min_width_start = it->current_x;
5508 }
5509 }
5510 }
5511
5512 DEFUN ("get-display-property", Fget_display_property,
5513 Sget_display_property, 2, 4, 0,
5514 doc:
5515
5516
5517
5518
5519 )
5520 (Lisp_Object position, Lisp_Object prop, Lisp_Object object,
5521 Lisp_Object properties)
5522 {
5523 if (NILP (properties))
5524 properties = Fget_text_property (position, Qdisplay, object);
5525 else
5526 CHECK_LIST (properties);
5527
5528 return find_display_property (properties, prop);
5529 }
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543 static enum prop_handled
5544 handle_display_prop (struct it *it)
5545 {
5546 Lisp_Object propval, object, overlay;
5547 struct text_pos *position;
5548 ptrdiff_t bufpos;
5549
5550 int display_replaced = 0;
5551
5552 if (STRINGP (it->string))
5553 {
5554 object = it->string;
5555 position = &it->current.string_pos;
5556 bufpos = CHARPOS (it->current.pos);
5557 }
5558 else
5559 {
5560 XSETWINDOW (object, it->w);
5561 position = &it->current.pos;
5562 bufpos = CHARPOS (*position);
5563 }
5564
5565
5566 it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
5567 it->space_width = Qnil;
5568 it->font_height = Qnil;
5569 it->voffset = 0;
5570
5571
5572
5573
5574 if (!it->string_from_display_prop_p)
5575 it->area = TEXT_AREA;
5576
5577 propval = get_char_property_and_overlay (make_fixnum (position->charpos),
5578 Qdisplay, object, &overlay);
5579
5580
5581 if (!STRINGP (it->string))
5582 object = it->w->contents;
5583
5584
5585 if (!NILP (it->min_width_property)
5586 && NILP (find_display_property (propval, Qmin_width)))
5587 display_min_width (it, bufpos, object, Qnil);
5588
5589 if (NILP (propval))
5590 return HANDLED_NORMALLY;
5591
5592
5593
5594 display_replaced = handle_display_spec (it, propval, object, overlay,
5595 position, bufpos,
5596 FRAME_WINDOW_P (it->f));
5597 return display_replaced != 0 ? HANDLED_RETURN : HANDLED_NORMALLY;
5598 }
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616 static int
5617 handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5618 Lisp_Object overlay, struct text_pos *position,
5619 ptrdiff_t bufpos, bool frame_window_p)
5620 {
5621 int replacing = 0;
5622 bool enable_eval = true;
5623
5624
5625 if (CONSP (spec) && EQ (XCAR (spec), Qdisable_eval))
5626 {
5627 enable_eval = false;
5628 spec = CONSP (XCDR (spec)) ? XCAR (XCDR (spec)) : Qnil;
5629 }
5630
5631 if (CONSP (spec)
5632
5633 && !EQ (XCAR (spec), Qimage)
5634 #ifdef HAVE_XWIDGETS
5635 && !EQ (XCAR (spec), Qxwidget)
5636 #endif
5637 && !EQ (XCAR (spec), Qspace)
5638 && !EQ (XCAR (spec), Qwhen)
5639 && !EQ (XCAR (spec), Qslice)
5640 && !EQ (XCAR (spec), Qspace_width)
5641 && !EQ (XCAR (spec), Qheight)
5642 && !EQ (XCAR (spec), Qraise)
5643
5644 && !(CONSP (XCAR (spec)) && EQ (XCAR (XCAR (spec)), Qmargin))
5645 && !EQ (XCAR (spec), Qleft_fringe)
5646 && !EQ (XCAR (spec), Qright_fringe)
5647 && !EQ (XCAR (spec), Qmin_width)
5648 && !NILP (XCAR (spec)))
5649 {
5650 for (; CONSP (spec); spec = XCDR (spec))
5651 {
5652 int rv = handle_single_display_spec (it, XCAR (spec), object,
5653 overlay, position, bufpos,
5654 replacing, frame_window_p,
5655 enable_eval);
5656 if (rv != 0)
5657 {
5658 replacing = rv;
5659
5660
5661 if (!it || STRINGP (object))
5662 break;
5663 }
5664 }
5665 }
5666 else if (VECTORP (spec))
5667 {
5668 ptrdiff_t i;
5669 for (i = 0; i < ASIZE (spec); ++i)
5670 {
5671 int rv = handle_single_display_spec (it, AREF (spec, i), object,
5672 overlay, position, bufpos,
5673 replacing, frame_window_p,
5674 enable_eval);
5675 if (rv != 0)
5676 {
5677 replacing = rv;
5678
5679
5680 if (!it || STRINGP (object))
5681 break;
5682 }
5683 }
5684 }
5685 else
5686 replacing = handle_single_display_spec (it, spec, object, overlay, position,
5687 bufpos, 0, frame_window_p,
5688 enable_eval);
5689 return replacing;
5690 }
5691
5692
5693
5694
5695 static struct text_pos
5696 display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
5697 {
5698 Lisp_Object end;
5699 struct text_pos end_pos;
5700
5701 end = Fnext_single_char_property_change (make_fixnum (CHARPOS (start_pos)),
5702 Qdisplay, object, Qnil);
5703 CHARPOS (end_pos) = XFIXNAT (end);
5704 if (STRINGP (object))
5705 compute_string_pos (&end_pos, start_pos, it->string);
5706 else
5707 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFIXNAT (end));
5708
5709 return end_pos;
5710 }
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738 static int
5739 handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5740 Lisp_Object overlay, struct text_pos *position,
5741 ptrdiff_t bufpos, int display_replaced,
5742 bool frame_window_p, bool enable_eval_p)
5743 {
5744 Lisp_Object form;
5745 Lisp_Object location, value;
5746 struct text_pos start_pos = *position;
5747 void *itdata = NULL;
5748
5749
5750
5751 form = Qt;
5752 if (CONSP (spec) && EQ (XCAR (spec), Qwhen))
5753 {
5754 spec = XCDR (spec);
5755 if (!CONSP (spec))
5756 return 0;
5757 form = XCAR (spec);
5758 spec = XCDR (spec);
5759 }
5760
5761 if (!NILP (form) && !EQ (form, Qt) && !enable_eval_p)
5762 form = Qnil;
5763 if (!NILP (form) && !EQ (form, Qt))
5764 {
5765 specpdl_ref count = SPECPDL_INDEX ();
5766
5767
5768
5769
5770
5771
5772 if (NILP (object))
5773 XSETBUFFER (object, current_buffer);
5774 specbind (Qobject, object);
5775 specbind (Qposition, make_fixnum (CHARPOS (*position)));
5776 specbind (Qbuffer_position, make_fixnum (bufpos));
5777
5778
5779 itdata = bidi_shelve_cache ();
5780 form = safe_eval (form);
5781 bidi_unshelve_cache (itdata, false);
5782 form = unbind_to (count, form);
5783 }
5784
5785 if (NILP (form))
5786 return 0;
5787
5788
5789 if (CONSP (spec)
5790 && EQ (XCAR (spec), Qheight)
5791 && CONSP (XCDR (spec)))
5792 {
5793 if (it)
5794 {
5795 if (!FRAME_WINDOW_P (it->f))
5796 return 0;
5797
5798 it->font_height = XCAR (XCDR (spec));
5799 if (!NILP (it->font_height))
5800 {
5801 int new_height = -1;
5802
5803 if (CONSP (it->font_height)
5804 && (EQ (XCAR (it->font_height), Qplus)
5805 || EQ (XCAR (it->font_height), Qminus))
5806 && CONSP (XCDR (it->font_height))
5807 && RANGED_FIXNUMP (0, XCAR (XCDR (it->font_height)), INT_MAX))
5808 {
5809
5810 int steps = XFIXNUM (XCAR (XCDR (it->font_height)));
5811 if (EQ (XCAR (it->font_height), Qplus))
5812 steps = - steps;
5813 it->face_id = smaller_face (it->f, it->face_id, steps);
5814 }
5815 else if (FUNCTIONP (it->font_height) && enable_eval_p)
5816 {
5817
5818
5819 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5820 Lisp_Object height;
5821 itdata = bidi_shelve_cache ();
5822 height = safe_call1 (it->font_height,
5823 face->lface[LFACE_HEIGHT_INDEX]);
5824 bidi_unshelve_cache (itdata, false);
5825 if (NUMBERP (height))
5826 new_height = XFLOATINT (height);
5827 }
5828 else if (NUMBERP (it->font_height))
5829 {
5830
5831 struct face *f;
5832
5833 f = FACE_FROM_ID (it->f,
5834 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID));
5835 new_height = (XFLOATINT (it->font_height)
5836 * XFIXNUM (f->lface[LFACE_HEIGHT_INDEX]));
5837 }
5838 else if (enable_eval_p)
5839 {
5840
5841
5842 specpdl_ref count = SPECPDL_INDEX ();
5843 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5844
5845 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
5846 itdata = bidi_shelve_cache ();
5847 value = safe_eval (it->font_height);
5848 bidi_unshelve_cache (itdata, false);
5849 value = unbind_to (count, value);
5850
5851 if (NUMBERP (value))
5852 new_height = XFLOATINT (value);
5853 }
5854
5855 if (new_height > 0)
5856 it->face_id = face_with_height (it->f, it->face_id, new_height);
5857 }
5858 }
5859
5860 return 0;
5861 }
5862
5863
5864 if (CONSP (spec)
5865 && EQ (XCAR (spec), Qspace_width)
5866 && CONSP (XCDR (spec)))
5867 {
5868 if (it)
5869 {
5870 if (!FRAME_WINDOW_P (it->f))
5871 return 0;
5872
5873 value = XCAR (XCDR (spec));
5874 if (NUMBERP (value) && XFLOATINT (value) > 0)
5875 it->space_width = value;
5876 }
5877
5878 return 0;
5879 }
5880
5881
5882 if (CONSP (spec)
5883 && EQ (XCAR (spec), Qmin_width)
5884 && CONSP (XCDR (spec))
5885 && CONSP (XCAR (XCDR (spec))))
5886 {
5887 if (it)
5888 display_min_width (it, bufpos, object, XCAR (XCDR (spec)));
5889 return 0;
5890 }
5891
5892
5893 if (CONSP (spec)
5894 && EQ (XCAR (spec), Qslice))
5895 {
5896 Lisp_Object tem;
5897
5898 if (it)
5899 {
5900 if (!FRAME_WINDOW_P (it->f))
5901 return 0;
5902
5903 if (tem = XCDR (spec), CONSP (tem))
5904 {
5905 it->slice.x = XCAR (tem);
5906 if (tem = XCDR (tem), CONSP (tem))
5907 {
5908 it->slice.y = XCAR (tem);
5909 if (tem = XCDR (tem), CONSP (tem))
5910 {
5911 it->slice.width = XCAR (tem);
5912 if (tem = XCDR (tem), CONSP (tem))
5913 it->slice.height = XCAR (tem);
5914 }
5915 }
5916 }
5917 }
5918
5919 return 0;
5920 }
5921
5922
5923 if (CONSP (spec)
5924 && EQ (XCAR (spec), Qraise)
5925 && CONSP (XCDR (spec)))
5926 {
5927 if (it)
5928 {
5929 if (!FRAME_WINDOW_P (it->f))
5930 return 0;
5931
5932 #ifdef HAVE_WINDOW_SYSTEM
5933 value = XCAR (XCDR (spec));
5934 if (NUMBERP (value))
5935 {
5936 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5937 it->voffset = - (XFLOATINT (value)
5938 * (normal_char_height (face->font, -1)));
5939 }
5940 #endif
5941 }
5942
5943 return 0;
5944 }
5945
5946
5947
5948 if (it && it->string_from_display_prop_p)
5949 return 0;
5950
5951
5952
5953 if (it)
5954 {
5955 start_pos = *position;
5956 *position = display_prop_end (it, object, start_pos);
5957
5958
5959
5960
5961
5962
5963
5964 if (!NILP (overlay))
5965 {
5966 ptrdiff_t ovendpos = OVERLAY_END (overlay);
5967
5968
5969
5970
5971
5972
5973
5974 ovendpos = clip_to_bounds (BEGV, ovendpos, ZV);
5975
5976 if (ovendpos > CHARPOS (*position))
5977 SET_TEXT_POS (*position, ovendpos, CHAR_TO_BYTE (ovendpos));
5978 }
5979 }
5980 value = Qnil;
5981
5982
5983
5984 if (it)
5985 it->stop_charpos = position->charpos;
5986
5987
5988
5989 if (CONSP (spec)
5990 && (EQ (XCAR (spec), Qleft_fringe)
5991 || EQ (XCAR (spec), Qright_fringe))
5992 && CONSP (XCDR (spec)))
5993 {
5994 if (it)
5995 {
5996 if (!FRAME_WINDOW_P (it->f))
5997
5998
5999 {
6000
6001
6002
6003
6004 if (it->bidi_p)
6005 {
6006 it->position = *position;
6007 iterate_out_of_display_property (it);
6008 *position = it->position;
6009 }
6010 return 1;
6011 }
6012 }
6013 else if (!frame_window_p)
6014 return 1;
6015
6016 #ifdef HAVE_WINDOW_SYSTEM
6017 value = XCAR (XCDR (spec));
6018 int fringe_bitmap = SYMBOLP (value) ? lookup_fringe_bitmap (value) : 0;
6019 if (! fringe_bitmap)
6020
6021
6022 {
6023 if (it && it->bidi_p)
6024 {
6025 it->position = *position;
6026 iterate_out_of_display_property (it);
6027 *position = it->position;
6028 }
6029 return 1;
6030 }
6031
6032 if (it)
6033 {
6034 int face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
6035
6036 if (CONSP (XCDR (XCDR (spec))))
6037 {
6038 Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
6039 int face_id2;
6040
6041
6042
6043 specpdl_ref count1 = SPECPDL_INDEX ();
6044 specbind (Qinhibit_quit, Qt);
6045 face_id2 = lookup_derived_face (it->w, it->f, face_name,
6046 FRINGE_FACE_ID, false);
6047 unbind_to (count1, Qnil);
6048 if (face_id2 >= 0)
6049 face_id = face_id2;
6050 }
6051
6052
6053
6054 push_it (it, position);
6055
6056 it->area = TEXT_AREA;
6057 it->what = IT_IMAGE;
6058 it->image_id = -1;
6059 it->position = start_pos;
6060 it->object = NILP (object) ? it->w->contents : object;
6061 it->method = GET_FROM_IMAGE;
6062 it->from_overlay = Qnil;
6063 it->face_id = face_id;
6064 it->from_disp_prop_p = true;
6065
6066
6067
6068
6069 *position = start_pos;
6070
6071 if (EQ (XCAR (spec), Qleft_fringe))
6072 {
6073 it->left_user_fringe_bitmap = fringe_bitmap;
6074 it->left_user_fringe_face_id = face_id;
6075 }
6076 else
6077 {
6078 it->right_user_fringe_bitmap = fringe_bitmap;
6079 it->right_user_fringe_face_id = face_id;
6080 }
6081 }
6082 #endif
6083 return 1;
6084 }
6085
6086
6087
6088
6089 location = Qunbound;
6090 if (CONSP (spec) && CONSP (XCAR (spec)))
6091 {
6092 Lisp_Object tem;
6093
6094 value = XCDR (spec);
6095 if (CONSP (value))
6096 value = XCAR (value);
6097
6098 tem = XCAR (spec);
6099 if (EQ (XCAR (tem), Qmargin)
6100 && (tem = XCDR (tem),
6101 tem = CONSP (tem) ? XCAR (tem) : Qnil,
6102 (NILP (tem)
6103 || EQ (tem, Qleft_margin)
6104 || EQ (tem, Qright_margin))))
6105 location = tem;
6106 }
6107
6108 if (BASE_EQ (location, Qunbound))
6109 {
6110 location = Qnil;
6111 value = spec;
6112 }
6113
6114
6115
6116
6117
6118
6119
6120
6121 bool valid_p = (STRINGP (value)
6122 #ifdef HAVE_WINDOW_SYSTEM
6123 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6124 && valid_image_p (value))
6125 #endif
6126 || (CONSP (value) && EQ (XCAR (value), Qspace))
6127 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6128 && valid_xwidget_spec_p (value)));
6129
6130 if (valid_p && display_replaced == 0)
6131 {
6132 int retval = 1;
6133
6134 if (!it)
6135 {
6136
6137
6138
6139 if (CONSP (value) && EQ (XCAR (value), Qspace) && NILP (location))
6140 retval = 2;
6141 return retval;
6142 }
6143
6144
6145
6146 push_it (it, position);
6147 it->from_overlay = overlay;
6148 it->from_disp_prop_p = true;
6149
6150 if (NILP (location))
6151 it->area = TEXT_AREA;
6152 else if (EQ (location, Qleft_margin))
6153 it->area = LEFT_MARGIN_AREA;
6154 else
6155 it->area = RIGHT_MARGIN_AREA;
6156
6157 if (STRINGP (value))
6158 {
6159 it->string = value;
6160 it->multibyte_p = STRING_MULTIBYTE (it->string);
6161 it->current.overlay_string_index = -1;
6162 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6163 it->end_charpos = it->string_nchars = SCHARS (it->string);
6164 it->method = GET_FROM_STRING;
6165 it->stop_charpos = 0;
6166 it->prev_stop = 0;
6167 it->base_level_stop = 0;
6168 it->string_from_display_prop_p = true;
6169 it->cmp_it.id = -1;
6170
6171
6172
6173 if (BUFFERP (object))
6174 *position = start_pos;
6175
6176
6177
6178
6179 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6180 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6181 else
6182 it->paragraph_embedding = L2R;
6183
6184
6185 if (it->bidi_p)
6186 {
6187 it->bidi_it.string.lstring = it->string;
6188 it->bidi_it.string.s = NULL;
6189 it->bidi_it.string.schars = it->end_charpos;
6190 it->bidi_it.string.bufpos = bufpos;
6191 it->bidi_it.string.from_disp_str = true;
6192 it->bidi_it.string.unibyte = !it->multibyte_p;
6193 it->bidi_it.w = it->w;
6194 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6195 }
6196 }
6197 else if (CONSP (value) && EQ (XCAR (value), Qspace))
6198 {
6199 it->method = GET_FROM_STRETCH;
6200 it->object = value;
6201 *position = it->position = start_pos;
6202 retval = 1 + (it->area == TEXT_AREA);
6203 }
6204 else if (valid_xwidget_spec_p (value))
6205 {
6206 it->what = IT_XWIDGET;
6207 it->method = GET_FROM_XWIDGET;
6208 it->position = start_pos;
6209 it->object = NILP (object) ? it->w->contents : object;
6210 *position = start_pos;
6211 it->xwidget = lookup_xwidget (value);
6212 }
6213 #ifdef HAVE_WINDOW_SYSTEM
6214 else
6215 {
6216 specpdl_ref count = SPECPDL_INDEX ();
6217
6218 it->what = IT_IMAGE;
6219
6220
6221
6222 specbind (Qinhibit_quit, Qt);
6223 it->image_id = lookup_image (it->f, value, it->face_id);
6224 unbind_to (count, Qnil);
6225 it->position = start_pos;
6226 it->object = NILP (object) ? it->w->contents : object;
6227 it->method = GET_FROM_IMAGE;
6228
6229
6230
6231
6232 *position = start_pos;
6233 }
6234 #endif
6235
6236 return retval;
6237 }
6238
6239
6240
6241 *position = start_pos;
6242 return 0;
6243 }
6244
6245
6246
6247
6248
6249
6250 bool
6251 display_prop_intangible_p (Lisp_Object prop, Lisp_Object overlay,
6252 ptrdiff_t charpos, ptrdiff_t bytepos)
6253 {
6254 bool frame_window_p = FRAME_WINDOW_P (XFRAME (selected_frame));
6255 struct text_pos position;
6256
6257 SET_TEXT_POS (position, charpos, bytepos);
6258 return (handle_display_spec (NULL, prop, Qnil, overlay,
6259 &position, charpos, frame_window_p)
6260 != 0);
6261 }
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272 static bool
6273 single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
6274 {
6275 if (EQ (string, prop))
6276 return true;
6277
6278
6279 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
6280 {
6281 prop = XCDR (prop);
6282 if (!CONSP (prop))
6283 return false;
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294 prop = XCDR (prop);
6295 }
6296
6297 if (CONSP (prop))
6298
6299 if (EQ (XCAR (prop), Qmargin))
6300 {
6301 prop = XCDR (prop);
6302 if (!CONSP (prop))
6303 return false;
6304
6305 prop = XCDR (prop);
6306 if (!CONSP (prop))
6307 return false;
6308 }
6309
6310 return EQ (prop, string) || (CONSP (prop) && EQ (XCAR (prop), string));
6311 }
6312
6313
6314
6315
6316 static bool
6317 display_prop_string_p (Lisp_Object prop, Lisp_Object string)
6318 {
6319 if (CONSP (prop)
6320 && !EQ (XCAR (prop), Qwhen)
6321 && !(CONSP (XCAR (prop)) && EQ (Qmargin, XCAR (XCAR (prop)))))
6322 {
6323
6324 while (CONSP (prop))
6325 {
6326 if (single_display_spec_string_p (XCAR (prop), string))
6327 return true;
6328 prop = XCDR (prop);
6329 }
6330 }
6331 else if (VECTORP (prop))
6332 {
6333
6334 ptrdiff_t i;
6335 for (i = 0; i < ASIZE (prop); ++i)
6336 if (single_display_spec_string_p (AREF (prop, i), string))
6337 return true;
6338 }
6339 else
6340 return single_display_spec_string_p (prop, string);
6341
6342 return false;
6343 }
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355 static ptrdiff_t
6356 string_buffer_position_lim (Lisp_Object string,
6357 ptrdiff_t from, ptrdiff_t to, bool back_p)
6358 {
6359 Lisp_Object limit, prop, pos;
6360 bool found = false;
6361
6362 pos = make_fixnum (max (from, BEGV));
6363
6364 if (!back_p)
6365 {
6366 limit = make_fixnum (min (to, ZV));
6367 while (!found && !EQ (pos, limit))
6368 {
6369 prop = Fget_char_property (pos, Qdisplay, Qnil);
6370 if (!NILP (prop) && display_prop_string_p (prop, string))
6371 found = true;
6372 else
6373 pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil,
6374 limit);
6375 }
6376 }
6377 else
6378 {
6379 limit = make_fixnum (max (to, BEGV));
6380 while (!found && !EQ (pos, limit))
6381 {
6382 prop = Fget_char_property (pos, Qdisplay, Qnil);
6383 if (!NILP (prop) && display_prop_string_p (prop, string))
6384 found = true;
6385 else
6386 pos = Fprevious_single_char_property_change (pos, Qdisplay, Qnil,
6387 limit);
6388 }
6389 }
6390
6391 return found ? XFIXNUM (pos) : 0;
6392 }
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403 static ptrdiff_t
6404 string_buffer_position (Lisp_Object string, ptrdiff_t around_charpos)
6405 {
6406 const int MAX_DISTANCE = 1000;
6407 ptrdiff_t forward_limit = min (around_charpos + MAX_DISTANCE, ZV);
6408 ptrdiff_t found = string_buffer_position_lim (string, around_charpos,
6409 forward_limit, false);
6410
6411 if (!found)
6412 {
6413 ptrdiff_t backward_limit = max (around_charpos - MAX_DISTANCE, BEGV);
6414 found = string_buffer_position_lim (string, around_charpos,
6415 backward_limit, true);
6416 }
6417 return found;
6418 }
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429 static enum prop_handled
6430 handle_composition_prop (struct it *it)
6431 {
6432 Lisp_Object prop, string;
6433 ptrdiff_t pos, pos_byte, start, end;
6434
6435 if (STRINGP (it->string))
6436 {
6437 unsigned char *s;
6438
6439 pos = IT_STRING_CHARPOS (*it);
6440 pos_byte = IT_STRING_BYTEPOS (*it);
6441 string = it->string;
6442 s = SDATA (string) + pos_byte;
6443 if (STRING_MULTIBYTE (string))
6444 it->c = STRING_CHAR (s);
6445 else
6446 it->c = *s;
6447 }
6448 else
6449 {
6450 pos = IT_CHARPOS (*it);
6451 pos_byte = IT_BYTEPOS (*it);
6452 string = Qnil;
6453 it->c = FETCH_CHAR (pos_byte);
6454 }
6455
6456
6457
6458
6459 if (find_composition (pos, -1, &start, &end, &prop, string)
6460 && composition_valid_p (start, end, prop)
6461 && (STRINGP (it->string) || (PT <= start || PT >= end)))
6462 {
6463 if (start < pos)
6464
6465
6466
6467 return HANDLED_NORMALLY;
6468 if (start != pos)
6469 {
6470 if (STRINGP (it->string))
6471 pos_byte = string_char_to_byte (it->string, start);
6472 else
6473 pos_byte = CHAR_TO_BYTE (start);
6474 }
6475 it->cmp_it.id = get_composition_id (start, pos_byte, end - start,
6476 prop, string);
6477
6478 if (it->cmp_it.id >= 0)
6479 {
6480 it->cmp_it.ch = -1;
6481 it->cmp_it.nchars = COMPOSITION_LENGTH (prop);
6482 it->cmp_it.nglyphs = -1;
6483 }
6484 }
6485
6486 return HANDLED_NORMALLY;
6487 }
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498 struct overlay_entry
6499 {
6500 Lisp_Object overlay;
6501 Lisp_Object string;
6502 EMACS_INT priority;
6503 bool after_string_p;
6504 };
6505
6506
6507
6508
6509
6510 static enum prop_handled
6511 handle_overlay_change (struct it *it)
6512 {
6513 if (!STRINGP (it->string) && get_overlay_strings (it, 0))
6514 return HANDLED_RECOMPUTE_PROPS;
6515 else
6516 return HANDLED_NORMALLY;
6517 }
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527 static void
6528 next_overlay_string (struct it *it)
6529 {
6530 ++it->current.overlay_string_index;
6531 if (it->current.overlay_string_index == it->n_overlay_strings)
6532 {
6533
6534
6535
6536
6537 it->ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
6538 pop_it (it);
6539 eassert (it->sp > 0
6540 || (NILP (it->string)
6541 && it->method == GET_FROM_BUFFER
6542 && it->stop_charpos >= BEGV
6543 && it->stop_charpos <= it->end_charpos));
6544 it->current.overlay_string_index = -1;
6545 it->n_overlay_strings = 0;
6546
6547
6548
6549
6550 if (it->sp > 0 && STRINGP (it->string) && !SCHARS (it->string))
6551 pop_it (it);
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561 if (it->overlay_strings_charpos == IT_CHARPOS (*it))
6562 it->ignore_overlay_strings_at_pos_p = true;
6563
6564
6565
6566
6567 if (NILP (it->string)
6568 && IT_CHARPOS (*it) >= it->end_charpos
6569 && it->overlay_strings_charpos >= it->end_charpos)
6570 it->overlay_strings_at_end_processed_p = true;
6571
6572
6573
6574
6575
6576
6577
6578 it->overlay_strings_charpos = -1;
6579 }
6580 else
6581 {
6582
6583
6584
6585
6586
6587
6588 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
6589
6590 if (it->current.overlay_string_index && i == 0)
6591 load_overlay_strings (it, it->overlay_strings_charpos);
6592
6593
6594
6595 it->string = it->overlay_strings[i];
6596 it->multibyte_p = STRING_MULTIBYTE (it->string);
6597 SET_TEXT_POS (it->current.string_pos, 0, 0);
6598 it->method = GET_FROM_STRING;
6599 it->stop_charpos = 0;
6600 it->end_charpos = SCHARS (it->string);
6601 if (it->cmp_it.stop_pos >= 0)
6602 it->cmp_it.stop_pos = 0;
6603 it->prev_stop = 0;
6604 it->base_level_stop = 0;
6605
6606
6607 if (it->bidi_p)
6608 {
6609 it->bidi_it.string.lstring = it->string;
6610 it->bidi_it.string.s = NULL;
6611 it->bidi_it.string.schars = SCHARS (it->string);
6612 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
6613 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6614 it->bidi_it.string.unibyte = !it->multibyte_p;
6615 it->bidi_it.w = it->w;
6616 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6617 }
6618 }
6619
6620 CHECK_IT (it);
6621 }
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640 static int
6641 compare_overlay_entries (const void *e1, const void *e2)
6642 {
6643 struct overlay_entry const *entry1 = e1;
6644 struct overlay_entry const *entry2 = e2;
6645 int result;
6646
6647 if (entry1->after_string_p != entry2->after_string_p)
6648 {
6649
6650
6651 if (EQ (entry1->overlay, entry2->overlay))
6652 result = entry1->after_string_p ? 1 : -1;
6653 else
6654 result = entry1->after_string_p ? -1 : 1;
6655 }
6656 else if (entry1->priority != entry2->priority)
6657 {
6658 if (entry1->after_string_p)
6659
6660 result = entry2->priority < entry1->priority ? -1 : 1;
6661 else
6662
6663 result = entry1->priority < entry2->priority ? -1 : 1;
6664 }
6665 else
6666 result = 0;
6667
6668 return result;
6669 }
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696 static void
6697 load_overlay_strings (struct it *it, ptrdiff_t charpos)
6698 {
6699 ptrdiff_t n = 0;
6700 struct overlay_entry entriesbuf[20];
6701 ptrdiff_t size = ARRAYELTS (entriesbuf);
6702 struct overlay_entry *entries = entriesbuf;
6703 struct itree_node *node;
6704
6705 USE_SAFE_ALLOCA;
6706
6707 if (charpos <= 0)
6708 charpos = IT_CHARPOS (*it);
6709
6710
6711
6712
6713
6714 #define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
6715 do \
6716 { \
6717 Lisp_Object priority; \
6718 \
6719 if (n == size) \
6720 { \
6721 struct overlay_entry *old = entries; \
6722 SAFE_NALLOCA (entries, 2, size); \
6723 memcpy (entries, old, size * sizeof *entries); \
6724 size *= 2; \
6725 } \
6726 \
6727 entries[n].string = (STRING); \
6728 entries[n].overlay = (OVERLAY); \
6729 priority = Foverlay_get ((OVERLAY), Qpriority); \
6730 entries[n].priority = FIXNUMP (priority) ? XFIXNUM (priority) : 0; \
6731 entries[n].after_string_p = (AFTER_P); \
6732 ++n; \
6733 } \
6734 while (false)
6735
6736
6737
6738 ITREE_FOREACH (node, current_buffer->overlays, charpos - 1, charpos + 1, DESCENDING)
6739 {
6740 Lisp_Object overlay = node->data;
6741 eassert (OVERLAYP (overlay));
6742 ptrdiff_t start = node->begin;
6743 ptrdiff_t end = node->end;
6744
6745
6746
6747 if (end != charpos && start != charpos)
6748 continue;
6749
6750
6751 Lisp_Object window = Foverlay_get (overlay, Qwindow);
6752 if (WINDOWP (window) && XWINDOW (window) != it->w)
6753 continue;
6754
6755
6756
6757
6758 Lisp_Object invisible = Foverlay_get (overlay, Qinvisible);
6759 int invis = TEXT_PROP_MEANS_INVISIBLE (invisible);
6760
6761
6762 Lisp_Object str;
6763 if ((start == charpos || (end == charpos && invis != 0))
6764 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
6765 && SCHARS (str))
6766 RECORD_OVERLAY_STRING (overlay, str, false);
6767
6768
6769 if ((end == charpos || (start == charpos && invis != 0))
6770 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
6771 && SCHARS (str))
6772 RECORD_OVERLAY_STRING (overlay, str, true);
6773 }
6774
6775 #undef RECORD_OVERLAY_STRING
6776
6777
6778 if (n > 1)
6779 qsort (entries, n, sizeof *entries, compare_overlay_entries);
6780
6781
6782 it->n_overlay_strings = n;
6783 it->overlay_strings_charpos = charpos;
6784
6785
6786
6787
6788 ptrdiff_t j = it->current.overlay_string_index;
6789 for (ptrdiff_t i = 0; i < OVERLAY_STRING_CHUNK_SIZE && j < n; i++, j++)
6790 {
6791 it->overlay_strings[i] = entries[j].string;
6792 it->string_overlays[i] = entries[j].overlay;
6793 }
6794
6795 CHECK_IT (it);
6796 SAFE_FREE ();
6797 }
6798
6799
6800
6801
6802
6803
6804 static bool
6805 get_overlay_strings_1 (struct it *it, ptrdiff_t charpos, bool compute_stop_p)
6806 {
6807
6808
6809
6810
6811
6812
6813
6814 it->current.overlay_string_index = 0;
6815 load_overlay_strings (it, charpos);
6816
6817
6818
6819
6820 if (it->n_overlay_strings)
6821 {
6822
6823
6824
6825 if (compute_stop_p)
6826 compute_stop_pos (it);
6827 eassert (it->face_id >= 0);
6828
6829
6830
6831 eassert (!compute_stop_p || it->sp == 0);
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841 if (!(!it->bidi_p
6842 && STRINGP (it->string) && !SCHARS (it->string)))
6843 push_it (it, NULL);
6844
6845
6846
6847 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6848 it->string = it->overlay_strings[0];
6849 it->from_overlay = Qnil;
6850 it->stop_charpos = 0;
6851 eassert (STRINGP (it->string));
6852 it->end_charpos = SCHARS (it->string);
6853 it->prev_stop = 0;
6854 it->base_level_stop = 0;
6855 it->multibyte_p = STRING_MULTIBYTE (it->string);
6856 it->method = GET_FROM_STRING;
6857 it->from_disp_prop_p = 0;
6858 it->cmp_it.id = -1;
6859
6860
6861
6862 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6863 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6864 else
6865 it->paragraph_embedding = L2R;
6866
6867
6868 if (it->bidi_p)
6869 {
6870 ptrdiff_t pos = (charpos > 0 ? charpos : IT_CHARPOS (*it));
6871
6872 it->bidi_it.string.lstring = it->string;
6873 it->bidi_it.string.s = NULL;
6874 it->bidi_it.string.schars = SCHARS (it->string);
6875 it->bidi_it.string.bufpos = pos;
6876 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6877 it->bidi_it.string.unibyte = !it->multibyte_p;
6878 it->bidi_it.w = it->w;
6879 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6880 }
6881 return true;
6882 }
6883
6884 it->current.overlay_string_index = -1;
6885 return false;
6886 }
6887
6888 static bool
6889 get_overlay_strings (struct it *it, ptrdiff_t charpos)
6890 {
6891 it->string = Qnil;
6892 it->method = GET_FROM_BUFFER;
6893
6894 get_overlay_strings_1 (it, charpos, true);
6895
6896 CHECK_IT (it);
6897
6898
6899 return STRINGP (it->string);
6900 }
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914 static void
6915 push_it (struct it *it, struct text_pos *position)
6916 {
6917 struct iterator_stack_entry *p;
6918
6919 eassert (it->sp < IT_STACK_SIZE);
6920 p = it->stack + it->sp;
6921
6922 p->stop_charpos = it->stop_charpos;
6923 p->prev_stop = it->prev_stop;
6924 p->base_level_stop = it->base_level_stop;
6925 p->cmp_it = it->cmp_it;
6926 eassert (it->face_id >= 0);
6927 p->face_id = it->face_id;
6928 p->string = it->string;
6929 p->method = it->method;
6930 p->from_overlay = it->from_overlay;
6931 switch (p->method)
6932 {
6933 case GET_FROM_IMAGE:
6934 p->u.image.object = it->object;
6935 p->u.image.image_id = it->image_id;
6936 p->u.image.slice = it->slice;
6937 break;
6938 case GET_FROM_STRETCH:
6939 p->u.stretch.object = it->object;
6940 break;
6941 case GET_FROM_XWIDGET:
6942 p->u.xwidget.object = it->object;
6943 break;
6944 case GET_FROM_BUFFER:
6945 case GET_FROM_DISPLAY_VECTOR:
6946 case GET_FROM_STRING:
6947 case GET_FROM_C_STRING:
6948 break;
6949 default:
6950 emacs_abort ();
6951 }
6952 p->position = position ? *position : it->position;
6953 p->current = it->current;
6954 p->end_charpos = it->end_charpos;
6955 p->string_nchars = it->string_nchars;
6956 p->area = it->area;
6957 p->multibyte_p = it->multibyte_p;
6958 p->avoid_cursor_p = it->avoid_cursor_p;
6959 p->space_width = it->space_width;
6960 p->font_height = it->font_height;
6961 p->voffset = it->voffset;
6962 p->string_from_display_prop_p = it->string_from_display_prop_p;
6963 p->string_from_prefix_prop_p = it->string_from_prefix_prop_p;
6964 p->display_ellipsis_p = false;
6965 p->line_wrap = it->line_wrap;
6966 p->bidi_p = it->bidi_p;
6967 p->paragraph_embedding = it->paragraph_embedding;
6968 p->from_disp_prop_p = it->from_disp_prop_p;
6969 ++it->sp;
6970
6971
6972 if (it->bidi_p)
6973 bidi_push_it (&it->bidi_it);
6974 }
6975
6976 static void
6977 iterate_out_of_display_property (struct it *it)
6978 {
6979 bool buffer_p = !STRINGP (it->string);
6980 ptrdiff_t eob = (buffer_p ? ZV : it->end_charpos);
6981 ptrdiff_t bob = (buffer_p ? BEGV : 0);
6982
6983 eassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob);
6984
6985
6986
6987
6988 if (it->bidi_it.first_elt && it->bidi_it.charpos < eob)
6989 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
6990
6991 while (it->bidi_it.charpos >= bob
6992 && it->prev_stop <= it->bidi_it.charpos
6993 && it->bidi_it.charpos < CHARPOS (it->position)
6994 && it->bidi_it.charpos < eob)
6995 bidi_move_to_visually_next (&it->bidi_it);
6996
6997
6998 if (it->bidi_it.charpos > CHARPOS (it->position))
6999 it->prev_stop = CHARPOS (it->position);
7000
7001
7002 if (it->bidi_it.charpos != CHARPOS (it->position))
7003 SET_TEXT_POS (it->position, it->bidi_it.charpos, it->bidi_it.bytepos);
7004 if (buffer_p)
7005 it->current.pos = it->position;
7006 else
7007 it->current.string_pos = it->position;
7008 }
7009
7010
7011
7012
7013
7014 static void
7015 restore_face_box_flags (struct it *it, int prev_face_id)
7016 {
7017 struct face *face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
7018
7019 if (face)
7020 {
7021 struct face *prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
7022
7023 if (!(it->start_of_box_run_p && prev_face && prev_face->box))
7024 it->start_of_box_run_p = (face->box != FACE_NO_BOX
7025 && (prev_face == NULL
7026 || prev_face->box == FACE_NO_BOX));
7027 it->face_box_p = face->box != FACE_NO_BOX;
7028 }
7029 }
7030
7031
7032
7033
7034
7035
7036
7037 static void
7038 pop_it (struct it *it)
7039 {
7040 struct iterator_stack_entry *p;
7041 bool from_display_prop = it->from_disp_prop_p;
7042 ptrdiff_t prev_pos = IT_CHARPOS (*it);
7043 int prev_face_id = it->face_id;
7044
7045 eassert (it->sp > 0);
7046 --it->sp;
7047 p = it->stack + it->sp;
7048 it->stop_charpos = p->stop_charpos;
7049 it->prev_stop = p->prev_stop;
7050 it->base_level_stop = p->base_level_stop;
7051 it->cmp_it = p->cmp_it;
7052 it->face_id = p->face_id;
7053 it->current = p->current;
7054 it->position = p->position;
7055 it->string = p->string;
7056 it->from_overlay = p->from_overlay;
7057 if (NILP (it->string))
7058 SET_TEXT_POS (it->current.string_pos, -1, -1);
7059 it->method = p->method;
7060 switch (it->method)
7061 {
7062 case GET_FROM_IMAGE:
7063 it->image_id = p->u.image.image_id;
7064 it->object = p->u.image.object;
7065 it->slice = p->u.image.slice;
7066 break;
7067 case GET_FROM_XWIDGET:
7068 it->object = p->u.xwidget.object;
7069 break;
7070 case GET_FROM_STRETCH:
7071 it->object = p->u.stretch.object;
7072 break;
7073 case GET_FROM_BUFFER:
7074 {
7075 restore_face_box_flags (it, prev_face_id);
7076 it->object = it->w->contents;
7077 }
7078 break;
7079 case GET_FROM_STRING:
7080 {
7081 restore_face_box_flags (it, prev_face_id);
7082 it->object = it->string;
7083 }
7084 break;
7085 case GET_FROM_DISPLAY_VECTOR:
7086 if (it->s)
7087 it->method = GET_FROM_C_STRING;
7088 else if (STRINGP (it->string))
7089 it->method = GET_FROM_STRING;
7090 else
7091 {
7092 it->method = GET_FROM_BUFFER;
7093 it->object = it->w->contents;
7094 }
7095 break;
7096 case GET_FROM_C_STRING:
7097 break;
7098 default:
7099 emacs_abort ();
7100 }
7101 it->end_charpos = p->end_charpos;
7102 it->string_nchars = p->string_nchars;
7103 it->area = p->area;
7104 it->multibyte_p = p->multibyte_p;
7105 it->avoid_cursor_p = p->avoid_cursor_p;
7106 it->space_width = p->space_width;
7107 it->font_height = p->font_height;
7108 it->voffset = p->voffset;
7109 it->string_from_display_prop_p = p->string_from_display_prop_p;
7110 it->string_from_prefix_prop_p = p->string_from_prefix_prop_p;
7111 it->line_wrap = p->line_wrap;
7112 it->bidi_p = p->bidi_p;
7113 it->paragraph_embedding = p->paragraph_embedding;
7114 it->from_disp_prop_p = p->from_disp_prop_p;
7115 if (it->bidi_p)
7116 {
7117 bidi_pop_it (&it->bidi_it);
7118
7119
7120
7121
7122
7123
7124
7125 if (from_display_prop
7126 && (it->method == GET_FROM_BUFFER || it->method == GET_FROM_STRING))
7127 iterate_out_of_display_property (it);
7128
7129 eassert ((BUFFERP (it->object)
7130 && IT_CHARPOS (*it) == it->bidi_it.charpos
7131 && IT_BYTEPOS (*it) == it->bidi_it.bytepos)
7132 || (STRINGP (it->object)
7133 && IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
7134 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos)
7135 || (CONSP (it->object) && it->method == GET_FROM_STRETCH)
7136
7137
7138
7139
7140
7141
7142 || it->sp > 0);
7143 }
7144
7145
7146
7147 if (from_display_prop && it->sp == 0 && CHARPOS (it->position) != prev_pos)
7148 it->ignore_overlay_strings_at_pos_p = false;
7149 }
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159 static void
7160 back_to_previous_line_start (struct it *it)
7161 {
7162 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
7163
7164 dec_both (&cp, &bp);
7165 SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*it),
7166 find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)),
7167 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
7168 }
7169
7170
7171
7172
7173
7174 static bool
7175 strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w)
7176 {
7177 struct itree_node *node;
7178
7179 ITREE_FOREACH (node, current_buffer->overlays, startpos, endpos, DESCENDING)
7180 {
7181 Lisp_Object overlay = node->data;
7182 eassert (OVERLAYP (overlay));
7183
7184
7185 Lisp_Object window = Foverlay_get (overlay, Qwindow);
7186 if (WINDOWP (window) && XWINDOW (window) != w)
7187 continue;
7188
7189 ptrdiff_t ostart = node->begin;
7190 ptrdiff_t oend = node->end;
7191
7192
7193 if (!((startpos < oend && ostart < endpos)
7194 || (ostart == oend
7195 && (startpos == oend || (endpos == ZV && oend == endpos)))))
7196 continue;
7197
7198 Lisp_Object str;
7199 str = Foverlay_get (overlay, Qbefore_string);
7200 if (STRINGP (str) && SCHARS (str)
7201 && memchr (SDATA (str), '\n', SBYTES (str)))
7202 return true;
7203 str = Foverlay_get (overlay, Qafter_string);
7204 if (STRINGP (str) && SCHARS (str)
7205 && memchr (SDATA (str), '\n', SBYTES (str)))
7206 return true;
7207 }
7208
7209
7210 Lisp_Object cpos = make_fixnum (startpos);
7211 Lisp_Object limpos = make_fixnum (endpos);
7212
7213 while ((cpos = Fnext_single_property_change (cpos, Qdisplay, Qnil, limpos),
7214 !(NILP (cpos) || XFIXNAT (cpos) >= endpos)))
7215 {
7216 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
7217 Lisp_Object string = string_from_display_spec (spec);
7218 if (STRINGP (string)
7219 && memchr (SDATA (string), '\n', SBYTES (string)))
7220 return true;
7221 }
7222
7223 return false;
7224 }
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248 static bool
7249 forward_to_next_line_start (struct it *it, bool *skipped_p,
7250 struct bidi_it *bidi_it_prev)
7251 {
7252 ptrdiff_t old_selective;
7253 bool newline_found_p = false;
7254 int n;
7255 const int MAX_NEWLINE_DISTANCE = 500;
7256
7257
7258
7259 if (it->what == IT_CHARACTER
7260 && it->c == '\n'
7261 && CHARPOS (it->position) == IT_CHARPOS (*it))
7262 {
7263 if (it->bidi_p && bidi_it_prev)
7264 *bidi_it_prev = it->bidi_it;
7265 set_iterator_to_next (it, false);
7266 it->c = 0;
7267 return true;
7268 }
7269
7270
7271
7272
7273
7274 old_selective = it->selective;
7275 it->selective = 0;
7276
7277
7278
7279
7280 for (n = 0;
7281 !newline_found_p && n < MAX_NEWLINE_DISTANCE;
7282 n += !STRINGP (it->string))
7283 {
7284 if (!get_next_display_element (it))
7285 return false;
7286 newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
7287 if (newline_found_p && it->bidi_p && bidi_it_prev)
7288 *bidi_it_prev = it->bidi_it;
7289 set_iterator_to_next (it, false);
7290 }
7291
7292
7293
7294 if (!newline_found_p)
7295 {
7296 ptrdiff_t bytepos, start = IT_CHARPOS (*it);
7297 ptrdiff_t limit = find_newline_no_quit (start, IT_BYTEPOS (*it),
7298 1, &bytepos);
7299 eassert (!STRINGP (it->string));
7300
7301
7302
7303
7304 bool no_strings_with_newlines = it->stop_charpos >= limit;
7305
7306 if (!no_strings_with_newlines)
7307 {
7308 if (!(current_buffer->long_line_optimizations_p
7309 && it->line_wrap == TRUNCATE))
7310 {
7311
7312
7313 Lisp_Object pos =
7314 Fnext_single_property_change (make_fixnum (start),
7315 Qdisplay, Qnil,
7316 make_fixnum (limit));
7317 no_strings_with_newlines =
7318 (NILP (pos) || XFIXNAT (pos) == limit)
7319 && next_overlay_change (start) == ZV;
7320 }
7321 else
7322 {
7323
7324
7325
7326
7327 no_strings_with_newlines =
7328 !strings_with_newlines (start, limit, it->w);
7329 }
7330 }
7331
7332
7333
7334
7335 if (no_strings_with_newlines)
7336 {
7337 if (!it->bidi_p || !bidi_it_prev)
7338 {
7339
7340 IT_CHARPOS (*it) = limit;
7341 IT_BYTEPOS (*it) = bytepos;
7342 }
7343 else
7344 {
7345
7346
7347
7348 struct bidi_it bprev;
7349
7350
7351
7352
7353 if (it->bidi_it.disp_pos < limit)
7354 {
7355 it->bidi_it.disp_pos = limit;
7356 it->bidi_it.disp_prop = 0;
7357 }
7358 do {
7359 bprev = it->bidi_it;
7360 bidi_move_to_visually_next (&it->bidi_it);
7361 } while (it->bidi_it.charpos != limit);
7362 IT_CHARPOS (*it) = limit;
7363 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7364 if (bidi_it_prev)
7365 *bidi_it_prev = bprev;
7366 }
7367 *skipped_p = newline_found_p = true;
7368 }
7369 else
7370 {
7371
7372 while (!newline_found_p)
7373 {
7374 if (!get_next_display_element (it))
7375 break;
7376 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
7377 if (newline_found_p && it->bidi_p && bidi_it_prev)
7378 *bidi_it_prev = it->bidi_it;
7379 set_iterator_to_next (it, false);
7380 }
7381 }
7382 }
7383
7384 it->selective = old_selective;
7385 return newline_found_p;
7386 }
7387
7388
7389
7390
7391
7392
7393
7394 static void
7395 back_to_previous_visible_line_start (struct it *it)
7396 {
7397 while (IT_CHARPOS (*it) > BEGV)
7398 {
7399 back_to_previous_line_start (it);
7400
7401 if (IT_CHARPOS (*it) <= BEGV)
7402 break;
7403
7404
7405
7406 if (it->selective > 0
7407 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7408 it->selective))
7409 continue;
7410
7411
7412 {
7413 Lisp_Object prop;
7414 prop = Fget_char_property (make_fixnum (IT_CHARPOS (*it) - 1),
7415 Qinvisible, it->window);
7416 if (TEXT_PROP_MEANS_INVISIBLE (prop) != 0)
7417 continue;
7418 }
7419
7420 if (IT_CHARPOS (*it) <= BEGV)
7421 break;
7422
7423 {
7424 struct it it2;
7425 void *it2data = NULL;
7426 ptrdiff_t pos;
7427 ptrdiff_t beg, end;
7428 Lisp_Object val, overlay;
7429
7430 SAVE_IT (it2, *it, it2data);
7431
7432
7433 if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil)
7434 && beg < IT_CHARPOS (*it))
7435 goto replaced;
7436
7437
7438
7439 pos = --IT_CHARPOS (it2);
7440 --IT_BYTEPOS (it2);
7441 it2.sp = 0;
7442 bidi_unshelve_cache (NULL, false);
7443 it2.string_from_display_prop_p = false;
7444 it2.from_disp_prop_p = false;
7445 if (handle_display_prop (&it2) == HANDLED_RETURN
7446 && !NILP (val = get_char_property_and_overlay
7447 (make_fixnum (pos), Qdisplay, Qnil, &overlay))
7448 && (OVERLAYP (overlay)
7449 ? (beg = OVERLAY_START (overlay))
7450 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
7451 {
7452 RESTORE_IT (it, it, it2data);
7453 goto replaced;
7454 }
7455
7456
7457 RESTORE_IT (it, it, it2data);
7458 break;
7459
7460 replaced:
7461 if (beg < BEGV)
7462 beg = BEGV;
7463 IT_CHARPOS (*it) = beg;
7464 IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
7465 }
7466 }
7467
7468 it->continuation_lines_width = 0;
7469
7470 eassert (IT_CHARPOS (*it) >= BEGV);
7471 eassert (it->medium_narrowing_begv > 0
7472 || IT_CHARPOS (*it) == BEGV
7473 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7474 CHECK_IT (it);
7475 }
7476
7477
7478
7479
7480
7481
7482
7483 void
7484 reseat_at_previous_visible_line_start (struct it *it)
7485 {
7486 back_to_previous_visible_line_start (it);
7487 reseat (it, it->current.pos, true);
7488 CHECK_IT (it);
7489 }
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499 static void
7500 reseat_at_next_visible_line_start (struct it *it, bool on_newline_p)
7501 {
7502 bool skipped_p = false;
7503 struct bidi_it bidi_it_prev;
7504 bool newline_found_p
7505 = forward_to_next_line_start (it, &skipped_p,
7506 on_newline_p ? &bidi_it_prev : NULL);
7507
7508
7509
7510 if (it->selective > 0)
7511 while (IT_CHARPOS (*it) < ZV
7512 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7513 it->selective))
7514 {
7515 eassert (IT_BYTEPOS (*it) == BEGV
7516 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7517 newline_found_p =
7518 forward_to_next_line_start (it, &skipped_p,
7519 on_newline_p ? &bidi_it_prev : NULL);
7520 }
7521
7522
7523 if (on_newline_p && newline_found_p)
7524 {
7525 if (STRINGP (it->string))
7526 {
7527 if (IT_STRING_CHARPOS (*it) > 0)
7528 {
7529 if (!it->bidi_p)
7530 {
7531 --IT_STRING_CHARPOS (*it);
7532 --IT_STRING_BYTEPOS (*it);
7533 }
7534 else
7535 {
7536
7537
7538
7539 it->bidi_it = bidi_it_prev;
7540 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
7541 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
7542 }
7543 }
7544 }
7545 else if (IT_CHARPOS (*it) > BEGV)
7546 {
7547 if (!it->bidi_p)
7548 {
7549 --IT_CHARPOS (*it);
7550 --IT_BYTEPOS (*it);
7551 }
7552 else
7553 {
7554
7555
7556 it->bidi_it = bidi_it_prev;
7557 IT_CHARPOS (*it) = it->bidi_it.charpos;
7558 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7559 }
7560 reseat (it, it->current.pos, false);
7561 }
7562 }
7563 else if (skipped_p)
7564 reseat (it, it->current.pos, false);
7565
7566 CHECK_IT (it);
7567 }
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580 static void
7581 reseat (struct it *it, struct text_pos pos, bool force_p)
7582 {
7583 ptrdiff_t original_pos = IT_CHARPOS (*it);
7584
7585 reseat_1 (it, pos, false);
7586
7587 if (current_buffer->long_line_optimizations_p)
7588 {
7589 if (!it->medium_narrowing_begv)
7590 {
7591 it->medium_narrowing_begv
7592 = get_medium_narrowing_begv (it->w, window_point (it->w));
7593 it->medium_narrowing_zv
7594 = get_medium_narrowing_zv (it->w, window_point (it->w));
7595 it->large_narrowing_begv
7596 = get_large_narrowing_begv (window_point (it->w));
7597 it->large_narrowing_zv
7598 = get_large_narrowing_zv (window_point (it->w));
7599 }
7600 else if ((pos.charpos < it->medium_narrowing_begv
7601 || pos.charpos > it->medium_narrowing_zv)
7602 && (!redisplaying_p || it->line_wrap == TRUNCATE))
7603 {
7604 it->medium_narrowing_begv
7605 = get_medium_narrowing_begv (it->w, pos.charpos);
7606 it->medium_narrowing_zv
7607 = get_medium_narrowing_zv (it->w, pos.charpos);
7608 it->large_narrowing_begv
7609 = get_large_narrowing_begv (window_point (it->w));
7610 it->large_narrowing_zv
7611 = get_large_narrowing_zv (window_point (it->w));
7612 }
7613 }
7614
7615
7616
7617 if (force_p
7618 || CHARPOS (pos) > it->stop_charpos
7619 || CHARPOS (pos) < original_pos)
7620 {
7621 if (it->bidi_p)
7622 {
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633 if (CHARPOS (pos) != it->prev_stop)
7634 it->prev_stop = CHARPOS (pos);
7635 if (CHARPOS (pos) < it->base_level_stop)
7636 it->base_level_stop = 0;
7637 handle_stop (it);
7638 }
7639 else
7640 {
7641 handle_stop (it);
7642 it->prev_stop = it->base_level_stop = 0;
7643 }
7644
7645 }
7646
7647 CHECK_IT (it);
7648 }
7649
7650
7651
7652
7653
7654 static void
7655 reseat_1 (struct it *it, struct text_pos pos, bool set_stop_p)
7656 {
7657
7658 eassert (it->s == NULL);
7659
7660
7661 eassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
7662
7663 it->current.pos = it->position = pos;
7664 it->end_charpos = ZV;
7665 it->dpvec = NULL;
7666 it->current.dpvec_index = -1;
7667 it->current.overlay_string_index = -1;
7668 IT_STRING_CHARPOS (*it) = -1;
7669 IT_STRING_BYTEPOS (*it) = -1;
7670 it->string = Qnil;
7671 it->method = GET_FROM_BUFFER;
7672 it->object = it->w->contents;
7673 it->area = TEXT_AREA;
7674 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
7675 it->sp = 0;
7676 it->string_from_display_prop_p = false;
7677 it->string_from_prefix_prop_p = false;
7678
7679 it->from_disp_prop_p = false;
7680 it->face_before_selective_p = false;
7681 if (it->bidi_p)
7682 {
7683 bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7684 &it->bidi_it);
7685 bidi_unshelve_cache (NULL, false);
7686 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7687 it->bidi_it.string.s = NULL;
7688 it->bidi_it.string.lstring = Qnil;
7689 it->bidi_it.string.bufpos = 0;
7690 it->bidi_it.string.from_disp_str = false;
7691 it->bidi_it.string.unibyte = false;
7692 it->bidi_it.w = it->w;
7693 }
7694
7695 if (set_stop_p)
7696 {
7697 it->stop_charpos = CHARPOS (pos);
7698 it->base_level_stop = CHARPOS (pos);
7699 }
7700
7701 it->cmp_it.id = -1;
7702 it->min_width_property = Qnil;
7703 }
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724 static void
7725 reseat_to_string (struct it *it, const char *s, Lisp_Object string,
7726 ptrdiff_t charpos, ptrdiff_t precision, int field_width,
7727 int multibyte)
7728 {
7729
7730 it->stop_charpos = -1;
7731
7732
7733 memset (&it->current, 0, sizeof it->current);
7734 it->current.overlay_string_index = -1;
7735 it->current.dpvec_index = -1;
7736 eassert (charpos >= 0);
7737
7738
7739
7740 if (multibyte >= 0)
7741 it->multibyte_p = multibyte > 0;
7742
7743
7744
7745
7746
7747 it->bidi_p =
7748 !redisplay__inhibit_bidi
7749 && !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
7750
7751 if (s == NULL)
7752 {
7753 eassert (STRINGP (string));
7754 it->string = string;
7755 it->s = NULL;
7756 it->end_charpos = it->string_nchars = SCHARS (string);
7757 it->method = GET_FROM_STRING;
7758 it->current.string_pos = string_pos (charpos, string);
7759
7760 if (it->bidi_p)
7761 {
7762 it->bidi_it.string.lstring = string;
7763 it->bidi_it.string.s = NULL;
7764 it->bidi_it.string.schars = it->end_charpos;
7765 it->bidi_it.string.bufpos = 0;
7766 it->bidi_it.string.from_disp_str = false;
7767 it->bidi_it.string.unibyte = !it->multibyte_p;
7768 it->bidi_it.w = it->w;
7769 bidi_init_it (charpos, IT_STRING_BYTEPOS (*it),
7770 FRAME_WINDOW_P (it->f), &it->bidi_it);
7771 }
7772 }
7773 else
7774 {
7775 it->s = (const unsigned char *) s;
7776 it->string = Qnil;
7777
7778
7779
7780 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
7781 if (it->multibyte_p)
7782 {
7783 it->current.pos = c_string_pos (charpos, s, true);
7784 it->end_charpos = it->string_nchars = number_of_chars (s, true);
7785 }
7786 else
7787 {
7788 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
7789 it->end_charpos = it->string_nchars = strlen (s);
7790 }
7791
7792 if (it->bidi_p)
7793 {
7794 it->bidi_it.string.lstring = Qnil;
7795 it->bidi_it.string.s = (const unsigned char *) s;
7796 it->bidi_it.string.schars = it->end_charpos;
7797 it->bidi_it.string.bufpos = 0;
7798 it->bidi_it.string.from_disp_str = false;
7799 it->bidi_it.string.unibyte = !it->multibyte_p;
7800 it->bidi_it.w = it->w;
7801 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7802 &it->bidi_it);
7803 }
7804 it->method = GET_FROM_C_STRING;
7805 }
7806
7807
7808
7809 if (precision > 0 && it->end_charpos - charpos > precision)
7810 {
7811 it->end_charpos = it->string_nchars = charpos + precision;
7812 if (it->bidi_p)
7813 it->bidi_it.string.schars = it->end_charpos;
7814 }
7815
7816
7817
7818
7819
7820 if (field_width < 0)
7821 field_width = DISP_INFINITY;
7822
7823
7824
7825 if (field_width > it->end_charpos - charpos)
7826 it->end_charpos = charpos + field_width;
7827
7828
7829 if (DISP_TABLE_P (Vstandard_display_table))
7830 it->dp = XCHAR_TABLE (Vstandard_display_table);
7831
7832 it->stop_charpos = charpos;
7833 it->prev_stop = charpos;
7834 it->base_level_stop = 0;
7835 if (it->bidi_p)
7836 {
7837 it->bidi_it.first_elt = true;
7838 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7839 it->bidi_it.disp_pos = -1;
7840 }
7841 if (s == NULL && it->multibyte_p)
7842 {
7843 ptrdiff_t endpos = SCHARS (it->string);
7844 if (endpos > it->end_charpos)
7845 endpos = it->end_charpos;
7846 composition_compute_stop_pos (&it->cmp_it, charpos, -1, endpos,
7847 it->string);
7848 }
7849 CHECK_IT (it);
7850 }
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860 typedef bool (*next_element_function) (struct it *);
7861
7862 static next_element_function const get_next_element[NUM_IT_METHODS] =
7863 {
7864 next_element_from_buffer,
7865 next_element_from_display_vector,
7866 next_element_from_string,
7867 next_element_from_c_string,
7868 next_element_from_image,
7869 next_element_from_stretch,
7870 next_element_from_xwidget,
7871 };
7872
7873 #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884 #define CHAR_COMPOSED_P(IT,CHARPOS,BYTEPOS,END_CHARPOS) \
7885 ((IT)->cmp_it.id >= 0 \
7886 || ((IT)->cmp_it.stop_pos == (CHARPOS) \
7887 && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \
7888 END_CHARPOS, (IT)->w, \
7889 (IT)->bidi_p \
7890 ? (IT)->bidi_it.resolved_level \
7891 : -1, \
7892 FACE_FROM_ID_OR_NULL ((IT)->f, \
7893 (IT)->face_id), \
7894 (IT)->string)))
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904 Lisp_Object
7905 lookup_glyphless_char_display (int c, struct it *it)
7906 {
7907 Lisp_Object glyphless_method = Qnil;
7908
7909 if (CHAR_TABLE_P (Vglyphless_char_display)
7910 && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) >= 1)
7911 {
7912 if (c >= 0)
7913 glyphless_method = CHAR_TABLE_REF (Vglyphless_char_display, c);
7914 else
7915 glyphless_method = XCHAR_TABLE (Vglyphless_char_display)->extras[0];
7916
7917 if (CONSP (glyphless_method))
7918 glyphless_method = FRAME_WINDOW_P (it->f)
7919 ? XCAR (glyphless_method)
7920 : XCDR (glyphless_method);
7921 }
7922
7923 retry:
7924 if (NILP (glyphless_method))
7925 {
7926 if (c >= 0)
7927
7928 return Qnil;
7929
7930 glyphless_method = Qempty_box;
7931 }
7932 if (EQ (glyphless_method, Qzero_width))
7933 {
7934 if (c >= 0)
7935 return glyphless_method;
7936
7937 glyphless_method = Qempty_box;
7938 }
7939 if (EQ (glyphless_method, Qthin_space))
7940 it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE;
7941 else if (EQ (glyphless_method, Qempty_box))
7942 it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX;
7943 else if (EQ (glyphless_method, Qhex_code))
7944 it->glyphless_method = GLYPHLESS_DISPLAY_HEX_CODE;
7945 else if (STRINGP (glyphless_method))
7946 it->glyphless_method = GLYPHLESS_DISPLAY_ACRONYM;
7947 else
7948 {
7949
7950 glyphless_method = Qnil;
7951 goto retry;
7952 }
7953 it->what = IT_GLYPHLESS;
7954 return glyphless_method;
7955 }
7956
7957
7958
7959 static struct frame *last_escape_glyph_frame = NULL;
7960 static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
7961 static int last_escape_glyph_merged_face_id = 0;
7962
7963 static int
7964 merge_escape_glyph_face (struct it *it)
7965 {
7966 int face_id;
7967
7968 if (it->f == last_escape_glyph_frame
7969 && it->face_id == last_escape_glyph_face_id)
7970 face_id = last_escape_glyph_merged_face_id;
7971 else
7972 {
7973
7974 face_id = merge_faces (it->w, Qescape_glyph, 0, it->face_id);
7975 last_escape_glyph_frame = it->f;
7976 last_escape_glyph_face_id = it->face_id;
7977 last_escape_glyph_merged_face_id = face_id;
7978 }
7979 return face_id;
7980 }
7981
7982
7983
7984 static struct frame *last_glyphless_glyph_frame = NULL;
7985 static int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
7986 static int last_glyphless_glyph_merged_face_id = 0;
7987
7988 int
7989 merge_glyphless_glyph_face (struct it *it)
7990 {
7991 int face_id;
7992
7993 if (it->f == last_glyphless_glyph_frame
7994 && it->face_id == last_glyphless_glyph_face_id)
7995 face_id = last_glyphless_glyph_merged_face_id;
7996 else
7997 {
7998
7999 face_id = merge_faces (it->w, Qglyphless_char, 0, it->face_id);
8000 last_glyphless_glyph_frame = it->f;
8001 last_glyphless_glyph_face_id = it->face_id;
8002 last_glyphless_glyph_merged_face_id = face_id;
8003 }
8004 return face_id;
8005 }
8006
8007
8008
8009
8010 void
8011 forget_escape_and_glyphless_faces (void)
8012 {
8013 last_escape_glyph_frame = NULL;
8014 last_escape_glyph_face_id = (1 << FACE_ID_BITS);
8015 last_glyphless_glyph_frame = NULL;
8016 last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
8017 }
8018
8019
8020
8021
8022
8023 static bool
8024 get_next_display_element (struct it *it)
8025 {
8026
8027
8028
8029
8030 bool success_p;
8031
8032 get_next:
8033 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
8034
8035 if (it->what == IT_CHARACTER)
8036 {
8037
8038
8039
8040
8041
8042 if (it->bidi_p && it->bidi_it.type == STRONG_R
8043 && !inhibit_bidi_mirroring)
8044 it->c = bidi_mirror_char (it->c);
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054 if (success_p && it->dpvec == NULL)
8055 {
8056 Lisp_Object dv;
8057 struct charset *unibyte = CHARSET_FROM_ID (charset_unibyte);
8058 bool nonascii_space_p = false;
8059 bool nonascii_hyphen_p = false;
8060 int c = it->c;
8061
8062 if (! it->multibyte_p && ! ASCII_CHAR_P (c))
8063 {
8064 eassert (SINGLE_BYTE_CHAR_P (c));
8065 if (unibyte_display_via_language_environment)
8066 {
8067 c = DECODE_CHAR (unibyte, c);
8068 if (c < 0)
8069 c = BYTE8_TO_CHAR (it->c);
8070 }
8071 else
8072 c = BYTE8_TO_CHAR (it->c);
8073 }
8074
8075 if (it->dp
8076 && (dv = DISP_CHAR_VECTOR (it->dp, c),
8077 VECTORP (dv)))
8078 {
8079 struct Lisp_Vector *v = XVECTOR (dv);
8080
8081
8082
8083
8084 if (v->header.size)
8085 {
8086 it->dpvec_char_len = it->len;
8087 it->dpvec = v->contents;
8088 it->dpend = v->contents + v->header.size;
8089 it->current.dpvec_index = 0;
8090 it->dpvec_face_id = -1;
8091 it->saved_face_id = it->face_id;
8092 it->method = GET_FROM_DISPLAY_VECTOR;
8093 it->ellipsis_p = false;
8094 }
8095 else
8096 {
8097 set_iterator_to_next (it, false);
8098 }
8099 goto get_next;
8100 }
8101
8102 if (! NILP (lookup_glyphless_char_display (c, it)))
8103 {
8104 if (it->what == IT_GLYPHLESS)
8105 goto done;
8106
8107 set_iterator_to_next (it, false);
8108 goto get_next;
8109 }
8110
8111
8112
8113 if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
8114 {
8115 if (blankp (c))
8116 nonascii_space_p = true;
8117 else if (c == SOFT_HYPHEN || c == HYPHEN
8118 || c == NON_BREAKING_HYPHEN)
8119 nonascii_hyphen_p = true;
8120 }
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133 if (((c < ' ' || c == 127)
8134 ? (it->area != TEXT_AREA
8135
8136 || (c != '\t'
8137 && it->glyph_row
8138 && (it->glyph_row->mode_line_p || it->avoid_cursor_p))
8139 || (c != '\n' && c != '\t'))
8140 : (nonascii_space_p
8141 || nonascii_hyphen_p
8142 || CHAR_BYTE8_P (c)
8143 || ! CHAR_PRINTABLE_P (c))))
8144 {
8145
8146
8147
8148
8149
8150
8151 Lisp_Object gc;
8152 int ctl_len;
8153 int face_id;
8154 int lface_id = 0;
8155 int escape_glyph;
8156
8157
8158
8159 if (ASCII_CHAR_P (c) && it->ctl_arrow_p)
8160 {
8161 int g;
8162
8163 g = '^';
8164
8165 if (it->dp
8166 && (gc = DISP_CTRL_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8167 {
8168 g = GLYPH_CODE_CHAR (gc);
8169 lface_id = GLYPH_CODE_FACE (gc);
8170 }
8171
8172 face_id = (lface_id
8173 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8174 : merge_escape_glyph_face (it));
8175
8176 XSETINT (it->ctl_chars[0], g);
8177 XSETINT (it->ctl_chars[1], c ^ 0100);
8178 ctl_len = 2;
8179 goto display_control;
8180 }
8181
8182
8183
8184
8185 if (nonascii_space_p && EQ (Vnobreak_char_display, Qt))
8186 {
8187
8188 face_id = merge_faces (it->w, Qnobreak_space, 0,
8189 it->face_id);
8190 XSETINT (it->ctl_chars[0],
8191 nobreak_char_ascii_display ? ' ' : it->c);
8192 ctl_len = 1;
8193 goto display_control;
8194 }
8195
8196
8197
8198
8199 if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
8200 {
8201
8202 face_id = merge_faces (it->w, Qnobreak_hyphen, 0,
8203 it->face_id);
8204 XSETINT (it->ctl_chars[0],
8205 nobreak_char_ascii_display ? '-' : it->c);
8206 ctl_len = 1;
8207 goto display_control;
8208 }
8209
8210
8211
8212
8213 escape_glyph = '\\';
8214
8215 if (it->dp
8216 && (gc = DISP_ESCAPE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8217 {
8218 escape_glyph = GLYPH_CODE_CHAR (gc);
8219 lface_id = GLYPH_CODE_FACE (gc);
8220 }
8221
8222 face_id = (lface_id
8223 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8224 : merge_escape_glyph_face (it));
8225
8226
8227
8228 if (nonascii_space_p || nonascii_hyphen_p)
8229 {
8230 XSETINT (it->ctl_chars[0], escape_glyph);
8231 XSETINT (it->ctl_chars[1], nonascii_space_p ? ' ' : '-');
8232 ctl_len = 2;
8233 goto display_control;
8234 }
8235
8236 {
8237 char str[10];
8238 int len, i;
8239
8240 if (CHAR_BYTE8_P (c))
8241
8242 c = CHAR_TO_BYTE8 (c);
8243 const char *format_string = display_raw_bytes_as_hex
8244 ? "x%02x"
8245 : "%03o";
8246 len = sprintf (str, format_string, c + 0u);
8247
8248 XSETINT (it->ctl_chars[0], escape_glyph);
8249 for (i = 0; i < len; i++)
8250 XSETINT (it->ctl_chars[i + 1], str[i]);
8251 ctl_len = len + 1;
8252 }
8253
8254 display_control:
8255
8256 it->dpvec_char_len = it->len;
8257 it->dpvec = it->ctl_chars;
8258 it->dpend = it->dpvec + ctl_len;
8259 it->current.dpvec_index = 0;
8260 it->dpvec_face_id = face_id;
8261 it->saved_face_id = it->face_id;
8262 it->method = GET_FROM_DISPLAY_VECTOR;
8263 it->ellipsis_p = false;
8264 goto get_next;
8265 }
8266 it->char_to_display = c;
8267 }
8268 else if (success_p)
8269 {
8270 it->char_to_display = it->c;
8271 }
8272 }
8273
8274 #ifdef HAVE_WINDOW_SYSTEM
8275
8276
8277 if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION)
8278 && it->multibyte_p
8279 && success_p
8280 && FRAME_WINDOW_P (it->f))
8281 {
8282 struct face *face = FACE_FROM_ID (it->f, it->face_id);
8283
8284 if (it->what == IT_COMPOSITION && it->cmp_it.ch >= 0)
8285 {
8286
8287 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
8288
8289 it->face_id = face_for_font (it->f, LGSTRING_FONT (gstring), face);
8290 }
8291 else
8292 {
8293 ptrdiff_t pos = (it->s ? -1
8294 : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
8295 : IT_CHARPOS (*it));
8296 int c;
8297
8298 if (it->what == IT_CHARACTER)
8299 c = it->char_to_display;
8300 else
8301 {
8302 struct composition *cmp = composition_table[it->cmp_it.id];
8303 int i;
8304
8305 c = ' ';
8306 for (i = 0; i < cmp->glyph_len; i++)
8307
8308
8309 if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
8310 break;
8311 }
8312 it->face_id = FACE_FOR_CHAR (it->f, face, c, pos, it->string);
8313 }
8314 }
8315 #endif
8316
8317 done:
8318
8319
8320 if (it->face_box_p
8321 && it->s == NULL)
8322 {
8323 if (it->method == GET_FROM_STRING && it->sp)
8324 {
8325 int face_id = underlying_face_id (it);
8326 struct face *face = FACE_FROM_ID_OR_NULL (it->f, face_id);
8327
8328 if (face)
8329 {
8330 if (face->box == FACE_NO_BOX)
8331 {
8332
8333
8334 int string_face_id = face_after_it_pos (it);
8335 if (FACE_FROM_ID (it->f, string_face_id)->box == FACE_NO_BOX)
8336 it->end_of_box_run_p = true;
8337 }
8338
8339
8340
8341 else if (((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
8342
8343
8344
8345 || (it->what == IT_COMPOSITION
8346 && (IT_STRING_CHARPOS (*it) + it->cmp_it.nchars
8347 >= SCHARS (it->string))))
8348
8349
8350 && ((it->current.overlay_string_index >= 0
8351 && (it->current.overlay_string_index
8352 == it->n_overlay_strings - 1))
8353
8354 || it->from_disp_prop_p))
8355 {
8356 ptrdiff_t ignore;
8357 int next_face_id;
8358 bool text_from_string = false;
8359
8360
8361 struct text_pos pos = it->current.pos;
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373 if (it->from_disp_prop_p)
8374 {
8375 int stackp = it->sp - 1;
8376
8377
8378 while (stackp >= 0
8379 && STRINGP ((it->stack + stackp)->string))
8380 stackp--;
8381 if (stackp < 0)
8382 {
8383
8384
8385
8386
8387
8388
8389 text_from_string = true;
8390 pos = it->stack[it->sp - 1].position;
8391 }
8392 else
8393 pos = (it->stack + stackp)->position;
8394 }
8395 else
8396 INC_TEXT_POS (pos, it->multibyte_p);
8397
8398 if (text_from_string)
8399 {
8400 Lisp_Object base_string = it->stack[it->sp - 1].string;
8401
8402 if (CHARPOS (pos) >= SCHARS (base_string) - 1)
8403 it->end_of_box_run_p = true;
8404 else
8405 {
8406 next_face_id
8407 = face_at_string_position (it->w, base_string,
8408 CHARPOS (pos), 0,
8409 &ignore, face_id,
8410 false, 0);
8411 if (FACE_FROM_ID (it->f, next_face_id)->box
8412 == FACE_NO_BOX)
8413 it->end_of_box_run_p = true;
8414 }
8415 }
8416 else if (CHARPOS (pos) >= ZV)
8417 it->end_of_box_run_p = true;
8418 else
8419 {
8420 next_face_id =
8421 face_at_buffer_position (it->w, CHARPOS (pos),
8422 &ignore,
8423 CHARPOS (pos)
8424 + TEXT_PROP_DISTANCE_LIMIT,
8425 false, -1, 0);
8426 if (FACE_FROM_ID (it->f, next_face_id)->box
8427 == FACE_NO_BOX)
8428 it->end_of_box_run_p = true;
8429 }
8430 }
8431 }
8432 }
8433
8434
8435 else if (it->method != GET_FROM_DISPLAY_VECTOR)
8436 {
8437 int face_id = face_after_it_pos (it);
8438 if (face_id != it->face_id
8439 && FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX)
8440 it->end_of_box_run_p = true;
8441 }
8442 }
8443
8444
8445
8446
8447
8448 if (!success_p && it->sp > 0)
8449 {
8450 set_iterator_to_next (it, false);
8451 success_p = get_next_display_element (it);
8452 }
8453
8454
8455 return success_p;
8456 }
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474 void
8475 set_iterator_to_next (struct it *it, bool reseat_p)
8476 {
8477
8478 if (max_redisplay_ticks > 0)
8479 update_redisplay_ticks (1, it->w);
8480
8481 switch (it->method)
8482 {
8483 case GET_FROM_BUFFER:
8484
8485
8486
8487 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
8488 reseat_at_next_visible_line_start (it, false);
8489 else if (it->cmp_it.id >= 0)
8490 {
8491
8492 if (! it->bidi_p)
8493 {
8494 IT_CHARPOS (*it) += it->cmp_it.nchars;
8495 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
8496 }
8497 else
8498 {
8499 int i;
8500
8501
8502
8503
8504 for (i = 0; i < it->cmp_it.nchars; i++)
8505 bidi_move_to_visually_next (&it->bidi_it);
8506 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8507 IT_CHARPOS (*it) = it->bidi_it.charpos;
8508 }
8509
8510 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8511 && it->cmp_it.to < it->cmp_it.nglyphs)
8512 {
8513
8514
8515 it->cmp_it.from = it->cmp_it.to;
8516 }
8517 else if ((it->bidi_p && it->cmp_it.reversed_p)
8518 && it->cmp_it.from > 0)
8519 {
8520
8521
8522 it->cmp_it.to = it->cmp_it.from;
8523 }
8524 else
8525 {
8526
8527
8528 ptrdiff_t stop = it->end_charpos;
8529
8530 if (it->bidi_it.scan_dir < 0)
8531
8532
8533 stop = -1;
8534 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8535 IT_BYTEPOS (*it), stop, Qnil);
8536 }
8537 }
8538 else
8539 {
8540 eassert (it->len != 0);
8541
8542 if (!it->bidi_p)
8543 {
8544 IT_BYTEPOS (*it) += it->len;
8545 IT_CHARPOS (*it) += 1;
8546 }
8547 else
8548 {
8549 int prev_scan_dir = it->bidi_it.scan_dir;
8550
8551
8552 if (it->bidi_it.new_paragraph)
8553 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
8554 false);
8555 bidi_move_to_visually_next (&it->bidi_it);
8556 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8557 IT_CHARPOS (*it) = it->bidi_it.charpos;
8558 if (prev_scan_dir != it->bidi_it.scan_dir)
8559 {
8560
8561
8562 ptrdiff_t stop = it->end_charpos;
8563 if (it->bidi_it.scan_dir < 0)
8564 stop = -1;
8565 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8566 IT_BYTEPOS (*it), stop, Qnil);
8567 }
8568 }
8569 eassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
8570 }
8571 break;
8572
8573 case GET_FROM_C_STRING:
8574
8575 if (!it->bidi_p
8576
8577
8578
8579
8580 || IT_CHARPOS (*it) >= it->bidi_it.string.schars)
8581 {
8582 IT_BYTEPOS (*it) += it->len;
8583 IT_CHARPOS (*it) += 1;
8584 }
8585 else
8586 {
8587 bidi_move_to_visually_next (&it->bidi_it);
8588 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8589 IT_CHARPOS (*it) = it->bidi_it.charpos;
8590 }
8591 break;
8592
8593 case GET_FROM_DISPLAY_VECTOR:
8594
8595
8596
8597
8598 ++it->current.dpvec_index;
8599
8600
8601
8602 it->face_id = it->saved_face_id;
8603
8604 if (it->dpvec + it->current.dpvec_index >= it->dpend)
8605 {
8606 bool recheck_faces = it->ellipsis_p;
8607
8608 if (it->s)
8609 it->method = GET_FROM_C_STRING;
8610 else if (STRINGP (it->string))
8611 it->method = GET_FROM_STRING;
8612 else
8613 {
8614 it->method = GET_FROM_BUFFER;
8615 it->object = it->w->contents;
8616 }
8617
8618 it->dpvec = NULL;
8619 it->current.dpvec_index = -1;
8620
8621
8622 if (it->dpvec_char_len < 0)
8623 reseat_at_next_visible_line_start (it, true);
8624 else if (it->dpvec_char_len > 0)
8625 {
8626 it->len = it->dpvec_char_len;
8627 set_iterator_to_next (it, reseat_p);
8628 }
8629
8630
8631 if (recheck_faces)
8632 {
8633 if (it->method == GET_FROM_STRING)
8634 it->stop_charpos = IT_STRING_CHARPOS (*it);
8635 else
8636 it->stop_charpos = IT_CHARPOS (*it);
8637 }
8638 }
8639 break;
8640
8641 case GET_FROM_STRING:
8642
8643 eassert (it->s == NULL && STRINGP (it->string));
8644
8645
8646
8647
8648
8649 if (it->current.overlay_string_index >= 0)
8650 {
8651
8652
8653
8654 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8655 goto consider_string_end;
8656 }
8657 else
8658 {
8659
8660
8661 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
8662 goto consider_string_end;
8663 }
8664 if (it->cmp_it.id >= 0)
8665 {
8666
8667
8668
8669 if (! it->bidi_p)
8670 {
8671 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
8672 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
8673 }
8674 else
8675 {
8676 int i;
8677
8678 for (i = 0; i < it->cmp_it.nchars; i++)
8679 bidi_move_to_visually_next (&it->bidi_it);
8680 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8681 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8682 }
8683
8684
8685
8686 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8687 && (it->cmp_it.to < it->cmp_it.nglyphs))
8688 {
8689
8690
8691 it->cmp_it.from = it->cmp_it.to;
8692 }
8693 else if ((it->bidi_p && it->cmp_it.reversed_p)
8694 && it->cmp_it.from > 0)
8695 {
8696
8697
8698 it->cmp_it.to = it->cmp_it.from;
8699 }
8700 else
8701 {
8702
8703
8704
8705
8706
8707
8708 ptrdiff_t stop = SCHARS (it->string);
8709
8710 if (it->bidi_p && it->bidi_it.scan_dir < 0)
8711 stop = -1;
8712 else if (it->end_charpos < stop)
8713 {
8714
8715
8716
8717 stop = it->end_charpos;
8718 }
8719 composition_compute_stop_pos (&it->cmp_it,
8720 IT_STRING_CHARPOS (*it),
8721 IT_STRING_BYTEPOS (*it), stop,
8722 it->string);
8723 }
8724 }
8725 else
8726 {
8727 if (!it->bidi_p
8728
8729
8730
8731
8732
8733 || IT_STRING_CHARPOS (*it) >= it->bidi_it.string.schars)
8734 {
8735 IT_STRING_BYTEPOS (*it) += it->len;
8736 IT_STRING_CHARPOS (*it) += 1;
8737 }
8738 else
8739 {
8740 int prev_scan_dir = it->bidi_it.scan_dir;
8741
8742 bidi_move_to_visually_next (&it->bidi_it);
8743 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8744 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8745
8746
8747 if (prev_scan_dir != it->bidi_it.scan_dir)
8748 {
8749 ptrdiff_t stop = SCHARS (it->string);
8750
8751 if (it->bidi_it.scan_dir < 0)
8752 stop = -1;
8753 else if (it->end_charpos < stop)
8754 stop = it->end_charpos;
8755
8756 composition_compute_stop_pos (&it->cmp_it,
8757 IT_STRING_CHARPOS (*it),
8758 IT_STRING_BYTEPOS (*it), stop,
8759 it->string);
8760 }
8761 }
8762 }
8763
8764 consider_string_end:
8765
8766 if (it->current.overlay_string_index >= 0)
8767 {
8768
8769
8770 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8771 {
8772 it->ellipsis_p = false;
8773 next_overlay_string (it);
8774 if (it->ellipsis_p)
8775 setup_for_ellipsis (it, 0);
8776 }
8777 }
8778 else
8779 {
8780
8781
8782
8783
8784 if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
8785 && it->sp > 0)
8786 {
8787 pop_it (it);
8788 if (it->method == GET_FROM_STRING)
8789 goto consider_string_end;
8790 }
8791 }
8792 break;
8793
8794 case GET_FROM_IMAGE:
8795 case GET_FROM_STRETCH:
8796 case GET_FROM_XWIDGET:
8797
8798
8799
8800
8801 eassert (it->sp > 0);
8802 pop_it (it);
8803 if (it->method == GET_FROM_STRING)
8804 goto consider_string_end;
8805 break;
8806
8807 default:
8808
8809 emacs_abort ();
8810 }
8811
8812 eassert (it->method != GET_FROM_STRING
8813 || (STRINGP (it->string)
8814 && IT_STRING_CHARPOS (*it) >= 0));
8815 }
8816
8817
8818
8819
8820
8821
8822
8823
8824
8825
8826 static bool
8827 next_element_from_display_vector (struct it *it)
8828 {
8829 Lisp_Object gc;
8830 int prev_face_id = it->face_id;
8831 int next_face_id;
8832
8833
8834 eassert (it->dpvec && it->current.dpvec_index >= 0);
8835
8836 it->face_id = it->saved_face_id;
8837
8838
8839
8840 if (it->dpend - it->dpvec > 0
8841 && (gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc)))
8842 {
8843 struct face *this_face, *prev_face, *next_face;
8844
8845 it->c = GLYPH_CODE_CHAR (gc);
8846 it->len = CHAR_BYTES (it->c);
8847
8848
8849
8850
8851 if (it->dpvec_face_id >= 0)
8852 it->face_id = it->dpvec_face_id;
8853 else
8854 {
8855 int lface_id = GLYPH_CODE_FACE (gc);
8856 if (lface_id > 0)
8857 it->face_id = merge_faces (it->w, Qt, lface_id,
8858 it->saved_face_id);
8859 }
8860
8861
8862
8863
8864 this_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
8865 prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
8866
8867
8868 it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
8869 && (!prev_face
8870 || prev_face->box == FACE_NO_BOX));
8871
8872
8873
8874
8875 next_face_id = it->saved_face_id;
8876 if (it->current.dpvec_index < it->dpend - it->dpvec - 1)
8877 {
8878 if (it->dpvec_face_id >= 0)
8879 next_face_id = it->dpvec_face_id;
8880 else
8881 {
8882 Lisp_Object gc = it->dpvec[it->current.dpvec_index + 1];
8883 int lface_id = GLYPH_CODE_P (gc) ? GLYPH_CODE_FACE (gc) : 0;
8884
8885 if (lface_id > 0)
8886 next_face_id = merge_faces (it->w, Qt, lface_id,
8887 it->saved_face_id);
8888 }
8889 }
8890 next_face = FACE_FROM_ID_OR_NULL (it->f, next_face_id);
8891 if (this_face && this_face->box != FACE_NO_BOX
8892 && (!next_face || next_face->box == FACE_NO_BOX))
8893 it->end_of_box_run_p = true;
8894 it->face_box_p = this_face && this_face->box != FACE_NO_BOX;
8895 }
8896 else
8897
8898 it->c = ' ', it->len = 1;
8899
8900
8901
8902
8903 it->what = IT_CHARACTER;
8904 return true;
8905 }
8906
8907
8908
8909 static void
8910 get_visually_first_element (struct it *it)
8911 {
8912 bool string_p = STRINGP (it->string) || it->s;
8913 ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
8914 ptrdiff_t bob;
8915 ptrdiff_t obegv = BEGV;
8916
8917 SET_WITH_NARROWED_BEGV (it, bob,
8918 string_p ? 0 :
8919 IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
8920 it->medium_narrowing_begv);
8921
8922 if (STRINGP (it->string))
8923 {
8924 it->bidi_it.charpos = IT_STRING_CHARPOS (*it);
8925 it->bidi_it.bytepos = IT_STRING_BYTEPOS (*it);
8926 }
8927 else
8928 {
8929 it->bidi_it.charpos = IT_CHARPOS (*it);
8930 it->bidi_it.bytepos = IT_BYTEPOS (*it);
8931 }
8932
8933 if (it->bidi_it.charpos == eob)
8934 {
8935
8936
8937
8938 it->bidi_it.first_elt = false;
8939 }
8940 else if (it->bidi_it.charpos == bob
8941 || (!string_p
8942 && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
8943 || FETCH_BYTE (it->bidi_it.bytepos) == '\n')))
8944 {
8945
8946
8947 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8948 bidi_move_to_visually_next (&it->bidi_it);
8949 }
8950 else
8951 {
8952 ptrdiff_t orig_bytepos = it->bidi_it.bytepos;
8953
8954
8955
8956
8957 if (string_p)
8958 it->bidi_it.charpos = it->bidi_it.bytepos = 0;
8959 else
8960 SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos,
8961 find_newline_no_quit (IT_CHARPOS (*it),
8962 IT_BYTEPOS (*it), -1,
8963 &it->bidi_it.bytepos),
8964 it->medium_narrowing_begv);
8965 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8966 do
8967 {
8968
8969
8970 bidi_move_to_visually_next (&it->bidi_it);
8971 }
8972 while (it->bidi_it.bytepos != orig_bytepos
8973 && it->bidi_it.charpos < eob);
8974 }
8975
8976
8977 if (STRINGP (it->string))
8978 {
8979 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8980 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8981 }
8982 else
8983 {
8984 IT_CHARPOS (*it) = it->bidi_it.charpos;
8985 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8986 }
8987
8988 if (STRINGP (it->string) || !it->s)
8989 {
8990 ptrdiff_t stop, charpos, bytepos;
8991
8992 if (STRINGP (it->string))
8993 {
8994 eassert (!it->s);
8995 stop = SCHARS (it->string);
8996 if (stop > it->end_charpos)
8997 stop = it->end_charpos;
8998 charpos = IT_STRING_CHARPOS (*it);
8999 bytepos = IT_STRING_BYTEPOS (*it);
9000 }
9001 else
9002 {
9003 stop = it->end_charpos;
9004 charpos = IT_CHARPOS (*it);
9005 bytepos = IT_BYTEPOS (*it);
9006 }
9007 if (it->bidi_it.scan_dir < 0)
9008 stop = -1;
9009 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop,
9010 it->string);
9011 }
9012 }
9013
9014
9015
9016
9017
9018
9019 static bool
9020 next_element_from_string (struct it *it)
9021 {
9022 struct text_pos position;
9023
9024 eassert (STRINGP (it->string));
9025 eassert (!it->bidi_p || EQ (it->string, it->bidi_it.string.lstring));
9026 eassert (IT_STRING_CHARPOS (*it) >= 0);
9027 position = it->current.string_pos;
9028
9029
9030
9031
9032
9033 if (it->bidi_p && it->bidi_it.first_elt)
9034 {
9035 get_visually_first_element (it);
9036 SET_TEXT_POS (position, IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it));
9037 }
9038
9039
9040 if (IT_STRING_CHARPOS (*it) < it->end_charpos)
9041 {
9042 if (IT_STRING_CHARPOS (*it) >= it->stop_charpos)
9043 {
9044 if (!(!it->bidi_p
9045 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9046 || IT_STRING_CHARPOS (*it) == it->stop_charpos))
9047 {
9048
9049
9050
9051
9052
9053
9054 handle_stop_backwards (it, it->stop_charpos);
9055 return GET_NEXT_DISPLAY_ELEMENT (it);
9056 }
9057 else
9058 {
9059 if (it->bidi_p)
9060 {
9061
9062
9063 it->prev_stop = it->stop_charpos;
9064
9065
9066
9067 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9068 it->base_level_stop = it->stop_charpos;
9069 }
9070 handle_stop (it);
9071
9072
9073
9074 return GET_NEXT_DISPLAY_ELEMENT (it);
9075 }
9076 }
9077 else if (it->bidi_p
9078
9079
9080
9081 && IT_STRING_CHARPOS (*it) < it->prev_stop
9082
9083
9084
9085
9086 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9087 {
9088
9089
9090
9091
9092 if (it->base_level_stop <= 0
9093 || IT_STRING_CHARPOS (*it) < it->base_level_stop)
9094 it->base_level_stop = 0;
9095 handle_stop_backwards (it, it->base_level_stop);
9096 return GET_NEXT_DISPLAY_ELEMENT (it);
9097 }
9098 }
9099
9100 if (it->current.overlay_string_index >= 0)
9101 {
9102
9103
9104
9105 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
9106 {
9107 it->what = IT_EOB;
9108 return false;
9109 }
9110 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9111 IT_STRING_BYTEPOS (*it),
9112 it->bidi_it.scan_dir < 0
9113 ? -1
9114 : SCHARS (it->string))
9115 && next_element_from_composition (it))
9116 {
9117 return true;
9118 }
9119 else if (STRING_MULTIBYTE (it->string))
9120 {
9121 const unsigned char *s = (SDATA (it->string)
9122 + IT_STRING_BYTEPOS (*it));
9123 it->c = check_char_and_length (s, &it->len);
9124 }
9125 else
9126 {
9127 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9128 it->len = 1;
9129 }
9130 }
9131 else
9132 {
9133
9134
9135
9136
9137 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
9138 {
9139 it->what = IT_EOB;
9140 return false;
9141 }
9142 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
9143 {
9144
9145 it->c = ' ', it->len = 1;
9146 CHARPOS (position) = BYTEPOS (position) = -1;
9147 }
9148 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9149 IT_STRING_BYTEPOS (*it),
9150 it->bidi_it.scan_dir < 0
9151 ? -1
9152 : it->string_nchars)
9153 && next_element_from_composition (it))
9154 {
9155 return true;
9156 }
9157 else if (STRING_MULTIBYTE (it->string))
9158 {
9159 const unsigned char *s = (SDATA (it->string)
9160 + IT_STRING_BYTEPOS (*it));
9161 it->c = check_char_and_length (s, &it->len);
9162 }
9163 else
9164 {
9165 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9166 it->len = 1;
9167 }
9168 }
9169
9170
9171 it->what = IT_CHARACTER;
9172 it->object = it->string;
9173 it->position = position;
9174 return true;
9175 }
9176
9177
9178
9179
9180
9181
9182
9183
9184
9185 static bool
9186 next_element_from_c_string (struct it *it)
9187 {
9188 bool success_p = true;
9189
9190 eassert (it->s);
9191 eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
9192 it->what = IT_CHARACTER;
9193 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
9194 it->object = make_fixnum (0);
9195
9196
9197
9198
9199
9200 if (it->bidi_p && it->bidi_it.first_elt)
9201 get_visually_first_element (it);
9202
9203
9204
9205
9206 if (IT_CHARPOS (*it) >= it->end_charpos)
9207 {
9208
9209 it->what = IT_EOB;
9210 success_p = false;
9211 }
9212 else if (IT_CHARPOS (*it) >= it->string_nchars)
9213 {
9214
9215 it->c = ' ', it->len = 1;
9216 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
9217 }
9218 else if (it->multibyte_p)
9219 it->c = check_char_and_length (it->s + IT_BYTEPOS (*it), &it->len);
9220 else
9221 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
9222
9223 return success_p;
9224 }
9225
9226
9227
9228
9229
9230
9231
9232 static bool
9233 next_element_from_ellipsis (struct it *it)
9234 {
9235 if (it->selective_display_ellipsis_p)
9236 setup_for_ellipsis (it, it->len);
9237 else
9238 {
9239
9240
9241
9242
9243 it->saved_face_id = it->face_id;
9244 it->method = GET_FROM_BUFFER;
9245 it->object = it->w->contents;
9246 reseat_at_next_visible_line_start (it, true);
9247 it->face_before_selective_p = true;
9248 }
9249
9250 return GET_NEXT_DISPLAY_ELEMENT (it);
9251 }
9252
9253
9254
9255
9256
9257
9258
9259 static bool
9260 next_element_from_image (struct it *it)
9261 {
9262 it->what = IT_IMAGE;
9263 return true;
9264 }
9265
9266 static bool
9267 next_element_from_xwidget (struct it *it)
9268 {
9269 it->what = IT_XWIDGET;
9270 return true;
9271 }
9272
9273
9274
9275
9276
9277
9278 static bool
9279 next_element_from_stretch (struct it *it)
9280 {
9281 it->what = IT_STRETCH;
9282 return true;
9283 }
9284
9285
9286
9287
9288
9289
9290 static void
9291 compute_stop_pos_backwards (struct it *it)
9292 {
9293 const int SCAN_BACK_LIMIT = 1000;
9294 struct text_pos pos;
9295 struct display_pos save_current = it->current;
9296 struct text_pos save_position = it->position;
9297 ptrdiff_t charpos = IT_CHARPOS (*it);
9298 ptrdiff_t where_we_are = charpos;
9299 ptrdiff_t save_stop_pos = it->stop_charpos;
9300 ptrdiff_t save_end_pos = it->end_charpos;
9301
9302 eassert (NILP (it->string) && !it->s);
9303 eassert (it->bidi_p);
9304 it->bidi_p = false;
9305 do
9306 {
9307 it->end_charpos = min (charpos + 1, ZV);
9308 charpos = max (charpos - SCAN_BACK_LIMIT, BEGV);
9309 SET_TEXT_POS (pos, charpos, CHAR_TO_BYTE (charpos));
9310 reseat_1 (it, pos, false);
9311 compute_stop_pos (it);
9312
9313 if (it->stop_charpos <= charpos)
9314 emacs_abort ();
9315 }
9316 while (charpos > BEGV && it->stop_charpos >= it->end_charpos);
9317
9318 if (it->stop_charpos <= where_we_are)
9319 it->prev_stop = it->stop_charpos;
9320 else
9321 it->prev_stop = BEGV;
9322 it->bidi_p = true;
9323 it->current = save_current;
9324 it->position = save_position;
9325 it->stop_charpos = save_stop_pos;
9326 it->end_charpos = save_end_pos;
9327 }
9328
9329
9330
9331
9332
9333
9334
9335
9336
9337 static void
9338 handle_stop_backwards (struct it *it, ptrdiff_t charpos)
9339 {
9340 bool bufp = !STRINGP (it->string);
9341 ptrdiff_t where_we_are = (bufp ? IT_CHARPOS (*it) : IT_STRING_CHARPOS (*it));
9342 struct display_pos save_current = it->current;
9343 struct text_pos save_position = it->position;
9344 struct composition_it save_cmp_it = it->cmp_it;
9345 struct text_pos pos1;
9346 ptrdiff_t next_stop;
9347
9348
9349 eassert (it->bidi_p);
9350 it->bidi_p = false;
9351 do
9352 {
9353 it->prev_stop = charpos;
9354 if (bufp)
9355 {
9356 SET_TEXT_POS (pos1, charpos, CHAR_TO_BYTE (charpos));
9357 reseat_1 (it, pos1, false);
9358 }
9359 else
9360 it->current.string_pos = string_pos (charpos, it->string);
9361 compute_stop_pos (it);
9362
9363 if (it->stop_charpos <= it->prev_stop)
9364 emacs_abort ();
9365 charpos = it->stop_charpos;
9366 }
9367 while (charpos <= where_we_are);
9368
9369 it->bidi_p = true;
9370 it->current = save_current;
9371 it->position = save_position;
9372 it->cmp_it = save_cmp_it;
9373 next_stop = it->stop_charpos;
9374 it->stop_charpos = it->prev_stop;
9375 handle_stop (it);
9376 it->stop_charpos = next_stop;
9377 }
9378
9379
9380
9381
9382
9383
9384 static bool
9385 next_element_from_buffer (struct it *it)
9386 {
9387 bool success_p = true;
9388
9389 eassert (IT_CHARPOS (*it) >= BEGV);
9390 eassert (NILP (it->string) && !it->s);
9391 eassert (!it->bidi_p
9392 || (NILP (it->bidi_it.string.lstring)
9393 && it->bidi_it.string.s == NULL));
9394
9395
9396
9397
9398
9399 if (it->bidi_p && it->bidi_it.first_elt)
9400 {
9401 get_visually_first_element (it);
9402 SET_TEXT_POS (it->position, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9403 }
9404
9405 if (IT_CHARPOS (*it) >= it->stop_charpos)
9406 {
9407 if (IT_CHARPOS (*it) >= it->end_charpos)
9408 {
9409 bool overlay_strings_follow_p;
9410
9411
9412
9413 if (it->overlay_strings_at_end_processed_p)
9414 overlay_strings_follow_p = false;
9415 else
9416 {
9417 it->overlay_strings_at_end_processed_p = true;
9418 overlay_strings_follow_p = get_overlay_strings (it, 0);
9419 }
9420
9421 if (overlay_strings_follow_p)
9422 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
9423 else
9424 {
9425 it->what = IT_EOB;
9426 it->position = it->current.pos;
9427 success_p = false;
9428 }
9429 }
9430 else if (!(!it->bidi_p
9431 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9432 || IT_CHARPOS (*it) == it->stop_charpos))
9433 {
9434
9435
9436
9437
9438
9439
9440 handle_stop_backwards (it, it->stop_charpos);
9441 it->ignore_overlay_strings_at_pos_p = false;
9442 return GET_NEXT_DISPLAY_ELEMENT (it);
9443 }
9444 else
9445 {
9446 if (it->bidi_p)
9447 {
9448
9449
9450 it->prev_stop = it->stop_charpos;
9451
9452
9453
9454 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9455 it->base_level_stop = it->stop_charpos;
9456 }
9457 handle_stop (it);
9458 it->ignore_overlay_strings_at_pos_p = false;
9459 return GET_NEXT_DISPLAY_ELEMENT (it);
9460 }
9461 }
9462 else if (it->bidi_p
9463
9464
9465
9466 && IT_CHARPOS (*it) < it->prev_stop
9467
9468
9469
9470
9471 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9472 {
9473 if (it->base_level_stop <= 0
9474 || IT_CHARPOS (*it) < it->base_level_stop)
9475 {
9476
9477
9478
9479
9480 it->base_level_stop = BEGV;
9481 compute_stop_pos_backwards (it);
9482 handle_stop_backwards (it, it->prev_stop);
9483 }
9484 else
9485 handle_stop_backwards (it, it->base_level_stop);
9486 it->ignore_overlay_strings_at_pos_p = false;
9487 return GET_NEXT_DISPLAY_ELEMENT (it);
9488 }
9489 else
9490 {
9491
9492
9493 unsigned char *p;
9494 ptrdiff_t stop;
9495
9496
9497
9498 it->ignore_overlay_strings_at_pos_p = false;
9499
9500 if (composition_break_at_point
9501 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
9502 && !NILP (Vauto_composition_mode))
9503 {
9504
9505 if (it->bidi_it.scan_dir < 0)
9506 stop = (PT <= IT_CHARPOS (*it)) ? PT : -1;
9507 else
9508 stop = (IT_CHARPOS (*it) < PT
9509 && PT < it->end_charpos) ? PT : it->end_charpos;
9510 }
9511 else
9512 stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
9513 if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it),
9514 stop)
9515 && next_element_from_composition (it))
9516 {
9517 return true;
9518 }
9519
9520
9521 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
9522 if (it->multibyte_p && !ASCII_CHAR_P (*p))
9523 it->c = string_char_and_length (p, &it->len);
9524 else
9525 it->c = *p, it->len = 1;
9526
9527
9528 it->what = IT_CHARACTER;
9529 it->object = it->w->contents;
9530 it->position = it->current.pos;
9531
9532
9533
9534 if (it->selective)
9535 {
9536 if (it->c == '\n')
9537 {
9538
9539
9540 if (it->selective > 0
9541 && IT_CHARPOS (*it) + 1 < ZV
9542 && indented_beyond_p (IT_CHARPOS (*it) + 1,
9543 IT_BYTEPOS (*it) + 1,
9544 it->selective))
9545 {
9546 success_p = next_element_from_ellipsis (it);
9547 it->dpvec_char_len = -1;
9548 }
9549 }
9550 else if (it->c == '\r' && it->selective == -1)
9551 {
9552
9553
9554
9555 success_p = next_element_from_ellipsis (it);
9556 it->dpvec_char_len = -1;
9557 }
9558 }
9559 }
9560
9561
9562 eassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
9563 return success_p;
9564 }
9565
9566
9567
9568
9569
9570
9571
9572 static bool
9573 next_element_from_composition (struct it *it)
9574 {
9575 it->what = IT_COMPOSITION;
9576 it->len = it->cmp_it.nbytes;
9577 if (STRINGP (it->string))
9578 {
9579 if (it->c < 0)
9580 {
9581 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
9582 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
9583 return false;
9584 }
9585 it->position = it->current.string_pos;
9586 it->object = it->string;
9587 it->c = composition_update_it (&it->cmp_it, IT_STRING_CHARPOS (*it),
9588 IT_STRING_BYTEPOS (*it), it->string);
9589 }
9590 else
9591 {
9592 if (it->c < 0)
9593 {
9594 IT_CHARPOS (*it) += it->cmp_it.nchars;
9595 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
9596 if (it->bidi_p)
9597 {
9598 if (it->bidi_it.new_paragraph)
9599 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
9600 false);
9601
9602
9603 while (it->bidi_it.charpos < IT_CHARPOS (*it))
9604 bidi_move_to_visually_next (&it->bidi_it);
9605 }
9606 return false;
9607 }
9608 it->position = it->current.pos;
9609 it->object = it->w->contents;
9610 it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
9611 IT_BYTEPOS (*it), Qnil);
9612 }
9613 return true;
9614 }
9615
9616
9617
9618
9619
9620
9621
9622
9623
9624
9625 #define IT_POS_VALID_AFTER_MOVE_P(it) \
9626 ((it)->method != GET_FROM_STRING || IT_STRING_CHARPOS (*it) == 0)
9627
9628
9629
9630
9631
9632
9633
9634
9635
9636
9637
9638
9639
9640
9641
9642
9643
9644
9645
9646
9647
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659
9660
9661
9662 static enum move_it_result
9663 move_it_in_display_line_to (struct it *it,
9664 ptrdiff_t to_charpos, int to_x,
9665 enum move_operation_enum op)
9666 {
9667 enum move_it_result result = MOVE_UNDEFINED;
9668 struct glyph_row *saved_glyph_row;
9669 struct it wrap_it, atpos_it, atx_it, ppos_it;
9670 void *wrap_data = NULL, *atpos_data = NULL, *atx_data = NULL;
9671 void *ppos_data = NULL;
9672 bool may_wrap = false;
9673 enum it_method prev_method = it->method;
9674 ptrdiff_t closest_pos UNINIT;
9675 ptrdiff_t prev_pos = IT_CHARPOS (*it);
9676 bool saw_smaller_pos = prev_pos < to_charpos;
9677 bool line_number_pending = false;
9678
9679
9680 saved_glyph_row = it->glyph_row;
9681 it->glyph_row = NULL;
9682
9683
9684
9685
9686
9687
9688 wrap_it.sp = -1;
9689 atpos_it.sp = -1;
9690 atx_it.sp = -1;
9691
9692
9693
9694
9695
9696
9697
9698
9699 if (it->bidi_p)
9700 {
9701 if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos)
9702 {
9703 SAVE_IT (ppos_it, *it, ppos_data);
9704 closest_pos = IT_CHARPOS (*it);
9705 }
9706 else
9707 closest_pos = ZV;
9708 }
9709
9710 #define BUFFER_POS_REACHED_P() \
9711 ((op & MOVE_TO_POS) != 0 \
9712 && BUFFERP (it->object) \
9713 && (IT_CHARPOS (*it) == to_charpos \
9714 || ((!it->bidi_p \
9715 || BIDI_AT_BASE_LEVEL (it->bidi_it)) \
9716 && IT_CHARPOS (*it) > to_charpos) \
9717 || (it->what == IT_COMPOSITION \
9718 && ((IT_CHARPOS (*it) > to_charpos \
9719 && to_charpos >= it->cmp_it.charpos) \
9720 || (IT_CHARPOS (*it) < to_charpos \
9721 && to_charpos <= it->cmp_it.charpos)))) \
9722 && (it->method == GET_FROM_BUFFER \
9723 || (it->method == GET_FROM_DISPLAY_VECTOR \
9724 && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
9725
9726 if (it->hpos == 0)
9727 {
9728
9729
9730
9731
9732 if (!((op && MOVE_TO_X) && to_x == it->first_visible_x)
9733 && should_produce_line_number (it))
9734 {
9735 if (it->current_x == it->first_visible_x)
9736 maybe_produce_line_number (it);
9737 else
9738 line_number_pending = true;
9739 }
9740
9741 if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p)
9742 handle_line_prefix (it);
9743 }
9744
9745 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9746 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9747
9748 while (true)
9749 {
9750 int x, i, ascent = 0, descent = 0;
9751
9752
9753 #define IT_RESET_X_ASCENT_DESCENT(IT) \
9754 ((IT)->current_x = x, (IT)->max_ascent = ascent, \
9755 (IT)->max_descent = descent)
9756
9757
9758
9759 if ((op & MOVE_TO_POS) != 0
9760 && BUFFERP (it->object)
9761 && it->method == GET_FROM_BUFFER
9762 && (((!it->bidi_p
9763
9764
9765
9766
9767 || BIDI_AT_BASE_LEVEL (it->bidi_it))
9768 && IT_CHARPOS (*it) > to_charpos)
9769 || (it->bidi_p
9770 && (prev_method == GET_FROM_IMAGE
9771 || prev_method == GET_FROM_STRETCH
9772 || prev_method == GET_FROM_STRING)
9773
9774 && ((prev_pos < to_charpos
9775 && IT_CHARPOS (*it) >= to_charpos)
9776
9777 || (prev_pos > to_charpos
9778 && IT_CHARPOS (*it) <= to_charpos)))))
9779 {
9780 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9781 {
9782 result = MOVE_POS_MATCH_OR_ZV;
9783 break;
9784 }
9785 else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
9786
9787
9788
9789 SAVE_IT (atpos_it, *it, atpos_data);
9790 }
9791
9792
9793
9794
9795
9796 if (!get_next_display_element (it))
9797 {
9798 result = MOVE_POS_MATCH_OR_ZV;
9799 break;
9800 }
9801
9802 if (it->line_wrap == TRUNCATE)
9803 {
9804
9805
9806
9807
9808
9809
9810 if (BUFFER_POS_REACHED_P ()
9811 && (it->pixel_width > 0
9812 || IT_CHARPOS (*it) > to_charpos
9813 || it->area != TEXT_AREA))
9814 {
9815 result = MOVE_POS_MATCH_OR_ZV;
9816 break;
9817 }
9818 }
9819 else
9820 {
9821 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
9822 {
9823 bool next_may_wrap = may_wrap;
9824
9825 if (char_can_wrap_after (it))
9826 next_may_wrap = true;
9827 else
9828 next_may_wrap = false;
9829
9830 if (may_wrap && char_can_wrap_before (it))
9831 {
9832
9833
9834
9835
9836
9837 if (atpos_it.sp >= 0)
9838 {
9839 RESTORE_IT (it, &atpos_it, atpos_data);
9840 result = MOVE_POS_MATCH_OR_ZV;
9841 goto done;
9842 }
9843 if (atx_it.sp >= 0)
9844 {
9845 RESTORE_IT (it, &atx_it, atx_data);
9846 result = MOVE_X_REACHED;
9847 goto done;
9848 }
9849
9850 SAVE_IT (wrap_it, *it, wrap_data);
9851 }
9852
9853 may_wrap = next_may_wrap;
9854 }
9855 }
9856
9857
9858
9859 ascent = it->max_ascent;
9860 descent = it->max_descent;
9861
9862
9863
9864
9865
9866 x = it->current_x;
9867
9868 PRODUCE_GLYPHS (it);
9869
9870 if (it->area != TEXT_AREA)
9871 {
9872 prev_method = it->method;
9873 if (it->method == GET_FROM_BUFFER)
9874 prev_pos = IT_CHARPOS (*it);
9875 set_iterator_to_next (it, true);
9876 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9877 SET_TEXT_POS (this_line_min_pos,
9878 IT_CHARPOS (*it), IT_BYTEPOS (*it));
9879 if (it->bidi_p
9880 && (op & MOVE_TO_POS)
9881 && IT_CHARPOS (*it) > to_charpos
9882 && IT_CHARPOS (*it) < closest_pos)
9883 closest_pos = IT_CHARPOS (*it);
9884 continue;
9885 }
9886
9887
9888
9889
9890
9891
9892
9893
9894
9895
9896
9897
9898
9899
9900
9901
9902
9903
9904
9905 if (it->nglyphs)
9906 {
9907
9908
9909 int single_glyph_width = it->pixel_width / it->nglyphs;
9910 int new_x;
9911 int x_before_this_char = x;
9912 int hpos_before_this_char = it->hpos;
9913
9914 for (i = 0; i < it->nglyphs; ++i, x = new_x)
9915 {
9916 new_x = x + single_glyph_width;
9917
9918
9919 if ((op & MOVE_TO_X) && new_x > to_x)
9920 {
9921 if (BUFFER_POS_REACHED_P ())
9922 {
9923 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9924 goto buffer_pos_reached;
9925 if (atpos_it.sp < 0)
9926 {
9927 SAVE_IT (atpos_it, *it, atpos_data);
9928 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
9929 }
9930 }
9931 else
9932 {
9933 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9934 {
9935 it->current_x = x;
9936 result = MOVE_X_REACHED;
9937 break;
9938 }
9939 if (atx_it.sp < 0)
9940 {
9941 SAVE_IT (atx_it, *it, atx_data);
9942 IT_RESET_X_ASCENT_DESCENT (&atx_it);
9943 }
9944 }
9945 }
9946
9947 if (
9948 it->line_wrap != TRUNCATE
9949 && (
9950 new_x > it->last_visible_x
9951
9952
9953 || (new_x == it->last_visible_x
9954 && FRAME_WINDOW_P (it->f)
9955 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
9956 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
9957 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
9958 {
9959 bool moved_forward = false;
9960
9961 if (
9962
9963 it->hpos == 0
9964 || (new_x == it->last_visible_x
9965 && FRAME_WINDOW_P (it->f)))
9966 {
9967 ++it->hpos;
9968 it->current_x = new_x;
9969
9970
9971
9972 if (i == it->nglyphs - 1)
9973 {
9974
9975
9976
9977 if (BUFFER_POS_REACHED_P ())
9978 {
9979 bool can_wrap = true;
9980
9981
9982
9983
9984
9985 if (it->line_wrap == WORD_WRAP
9986 && wrap_it.sp >= 0
9987 && may_wrap
9988 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
9989 {
9990 struct it tem_it;
9991 void *tem_data = NULL;
9992
9993 SAVE_IT (tem_it, *it, tem_data);
9994 set_iterator_to_next (it, true);
9995 if (get_next_display_element (it)
9996 && !char_can_wrap_before (it))
9997 can_wrap = false;
9998 RESTORE_IT (it, &tem_it, tem_data);
9999 }
10000 if (it->line_wrap != WORD_WRAP
10001 || wrap_it.sp < 0
10002
10003
10004
10005
10006
10007
10008
10009 || (may_wrap && can_wrap
10010 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10011 {
10012 it->hpos = hpos_before_this_char;
10013 it->current_x = x_before_this_char;
10014 result = MOVE_POS_MATCH_OR_ZV;
10015 break;
10016 }
10017 if (it->line_wrap == WORD_WRAP
10018 && atpos_it.sp < 0)
10019 {
10020 SAVE_IT (atpos_it, *it, atpos_data);
10021 atpos_it.current_x = x_before_this_char;
10022 atpos_it.hpos = hpos_before_this_char;
10023 }
10024 }
10025
10026 prev_method = it->method;
10027 if (it->method == GET_FROM_BUFFER)
10028 prev_pos = IT_CHARPOS (*it);
10029 set_iterator_to_next (it, true);
10030 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10031 SET_TEXT_POS (this_line_min_pos,
10032 IT_CHARPOS (*it), IT_BYTEPOS (*it));
10033
10034
10035
10036
10037
10038
10039
10040 if (!FRAME_WINDOW_P (it->f)
10041 || ((it->bidi_p
10042 && it->bidi_it.paragraph_dir == R2L)
10043 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10044 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10045 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10046 {
10047 if (!get_next_display_element (it))
10048 {
10049 result = MOVE_POS_MATCH_OR_ZV;
10050 break;
10051 }
10052 moved_forward = true;
10053 if (BUFFER_POS_REACHED_P ())
10054 {
10055 if (ITERATOR_AT_END_OF_LINE_P (it))
10056 result = MOVE_POS_MATCH_OR_ZV;
10057 else
10058 result = MOVE_LINE_CONTINUED;
10059 break;
10060 }
10061 if (ITERATOR_AT_END_OF_LINE_P (it)
10062 && (it->line_wrap != WORD_WRAP
10063 || wrap_it.sp < 0
10064 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10065 {
10066 result = MOVE_NEWLINE_OR_CR;
10067 break;
10068 }
10069 }
10070 }
10071 }
10072 else
10073 IT_RESET_X_ASCENT_DESCENT (it);
10074
10075
10076
10077
10078
10079
10080 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
10081
10082
10083
10084
10085
10086 && (!moved_forward || char_can_wrap_before (it)))
10087 {
10088
10089
10090 if ((op & MOVE_TO_X) && new_x == it->last_visible_x
10091 && atx_it.sp >= 0)
10092 {
10093 RESTORE_IT (it, &atx_it, atx_data);
10094 atpos_it.sp = -1;
10095 atx_it.sp = -1;
10096 result = MOVE_X_REACHED;
10097 break;
10098 }
10099 }
10100 else if (wrap_it.sp >= 0)
10101 {
10102 RESTORE_IT (it, &wrap_it, wrap_data);
10103 atpos_it.sp = -1;
10104 atx_it.sp = -1;
10105 }
10106
10107 move_trace ("move_it_in: continued at %td\n",
10108 IT_CHARPOS (*it));
10109 result = MOVE_LINE_CONTINUED;
10110 break;
10111 }
10112
10113 if (BUFFER_POS_REACHED_P ())
10114 {
10115 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
10116 goto buffer_pos_reached;
10117 if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
10118 {
10119 SAVE_IT (atpos_it, *it, atpos_data);
10120 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
10121 }
10122 }
10123
10124 if (new_x > it->first_visible_x)
10125 {
10126
10127
10128 if (line_number_pending)
10129 {
10130 line_number_pending = false;
10131 it->current_x = it->first_visible_x;
10132 maybe_produce_line_number (it);
10133 it->current_x += new_x - it->first_visible_x;
10134 }
10135
10136
10137 ++it->hpos;
10138 }
10139 }
10140
10141 if (result != MOVE_UNDEFINED)
10142 break;
10143 }
10144 else if (BUFFER_POS_REACHED_P ())
10145 {
10146 buffer_pos_reached:
10147 IT_RESET_X_ASCENT_DESCENT (it);
10148 result = MOVE_POS_MATCH_OR_ZV;
10149 break;
10150 }
10151 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
10152 {
10153
10154
10155
10156
10157 eassert (it->nglyphs == 0);
10158 result = MOVE_X_REACHED;
10159 break;
10160 }
10161
10162
10163 if (ITERATOR_AT_END_OF_LINE_P (it))
10164 {
10165
10166
10167
10168
10169 if (it->bidi_p && (op & MOVE_TO_POS) != 0)
10170 {
10171 if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos)
10172 {
10173 if (closest_pos < ZV)
10174 {
10175 RESTORE_IT (it, &ppos_it, ppos_data);
10176
10177
10178 if (closest_pos != to_charpos)
10179 move_it_in_display_line_to (it, closest_pos, -1,
10180 MOVE_TO_POS);
10181 result = MOVE_POS_MATCH_OR_ZV;
10182 }
10183 else
10184 goto buffer_pos_reached;
10185 }
10186 else if (it->line_wrap == WORD_WRAP && atpos_it.sp >= 0
10187 && IT_CHARPOS (*it) > to_charpos)
10188 goto buffer_pos_reached;
10189 else
10190 result = MOVE_NEWLINE_OR_CR;
10191 }
10192 else
10193 result = MOVE_NEWLINE_OR_CR;
10194
10195
10196
10197
10198 if (it->line_wrap == TRUNCATE
10199 && it->current_x <= it->first_visible_x
10200 && result == MOVE_NEWLINE_OR_CR
10201 && it->char_to_display == '\n')
10202 {
10203 it->max_ascent = it->ascent;
10204 it->max_descent = it->descent;
10205 }
10206
10207
10208
10209 if (result == MOVE_NEWLINE_OR_CR)
10210 it->constrain_row_ascent_descent_p = false;
10211 break;
10212 }
10213
10214 prev_method = it->method;
10215 if (it->method == GET_FROM_BUFFER)
10216 prev_pos = IT_CHARPOS (*it);
10217
10218
10219
10220
10221
10222
10223
10224
10225
10226 bool overwide_wrap_prefix =
10227 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
10228 && it->sp > 0 && it->method == GET_FROM_STRETCH
10229 && it->current_x >= it->last_visible_x
10230 && it->continuation_lines_width > 0
10231 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
10232
10233
10234 if (!overwide_wrap_prefix)
10235 set_iterator_to_next (it, true);
10236 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10237 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
10238 if (IT_CHARPOS (*it) < to_charpos)
10239 saw_smaller_pos = true;
10240 if (it->bidi_p
10241 && (op & MOVE_TO_POS)
10242 && IT_CHARPOS (*it) >= to_charpos
10243 && IT_CHARPOS (*it) < closest_pos)
10244 closest_pos = IT_CHARPOS (*it);
10245
10246
10247
10248 if (it->line_wrap == TRUNCATE
10249 && it->current_x >= it->last_visible_x)
10250 {
10251 if (!FRAME_WINDOW_P (it->f)
10252 || ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10253 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10254 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10255 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10256 {
10257 bool at_eob_p = false;
10258
10259 if ((at_eob_p = !get_next_display_element (it))
10260 || BUFFER_POS_REACHED_P ()
10261
10262
10263
10264
10265 || (it->bidi_p && (op & MOVE_TO_POS) != 0
10266 && !saw_smaller_pos
10267 && IT_CHARPOS (*it) > to_charpos))
10268 {
10269 if (it->bidi_p
10270 && !BUFFER_POS_REACHED_P ()
10271 && !at_eob_p && closest_pos < ZV)
10272 {
10273 RESTORE_IT (it, &ppos_it, ppos_data);
10274 if (closest_pos != to_charpos)
10275 move_it_in_display_line_to (it, closest_pos, -1,
10276 MOVE_TO_POS);
10277 }
10278 result = MOVE_POS_MATCH_OR_ZV;
10279 break;
10280 }
10281 if (ITERATOR_AT_END_OF_LINE_P (it))
10282 {
10283 result = MOVE_NEWLINE_OR_CR;
10284 break;
10285 }
10286 }
10287 else if (it->bidi_p && (op & MOVE_TO_POS) != 0
10288 && !saw_smaller_pos
10289 && IT_CHARPOS (*it) > to_charpos)
10290 {
10291 if (closest_pos < ZV)
10292 {
10293 RESTORE_IT (it, &ppos_it, ppos_data);
10294 if (closest_pos != to_charpos)
10295 move_it_in_display_line_to (it, closest_pos, -1,
10296 MOVE_TO_POS);
10297 }
10298 result = MOVE_POS_MATCH_OR_ZV;
10299 break;
10300 }
10301 result = MOVE_LINE_TRUNCATED;
10302 break;
10303 }
10304 #undef IT_RESET_X_ASCENT_DESCENT
10305 }
10306
10307 #undef BUFFER_POS_REACHED_P
10308
10309
10310
10311
10312
10313
10314 if (result == MOVE_LINE_CONTINUED
10315 && it->line_wrap == WORD_WRAP
10316 && wrap_it.sp >= 0
10317 && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
10318 || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
10319 RESTORE_IT (it, &wrap_it, wrap_data);
10320 else if (atpos_it.sp >= 0)
10321 RESTORE_IT (it, &atpos_it, atpos_data);
10322 else if (atx_it.sp >= 0)
10323 RESTORE_IT (it, &atx_it, atx_data);
10324
10325 done:
10326
10327 if (atpos_data)
10328 bidi_unshelve_cache (atpos_data, true);
10329 if (atx_data)
10330 bidi_unshelve_cache (atx_data, true);
10331 if (wrap_data)
10332 bidi_unshelve_cache (wrap_data, true);
10333 if (ppos_data)
10334 bidi_unshelve_cache (ppos_data, true);
10335
10336
10337
10338 it->glyph_row = saved_glyph_row;
10339 return result;
10340 }
10341
10342
10343 void
10344 move_it_in_display_line (struct it *it,
10345 ptrdiff_t to_charpos, int to_x,
10346 enum move_operation_enum op)
10347 {
10348 if (it->line_wrap == WORD_WRAP
10349 && (op & MOVE_TO_X))
10350 {
10351 struct it save_it;
10352 void *save_data = NULL;
10353 int skip;
10354
10355 SAVE_IT (save_it, *it, save_data);
10356 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10357
10358
10359
10360
10361 if (skip == MOVE_LINE_CONTINUED)
10362 {
10363 int prev_x = max (it->current_x - 1, 0);
10364 RESTORE_IT (it, &save_it, save_data);
10365 move_it_in_display_line_to
10366 (it, -1, prev_x, MOVE_TO_X);
10367 }
10368 else
10369 bidi_unshelve_cache (save_data, true);
10370 }
10371 else
10372 move_it_in_display_line_to (it, to_charpos, to_x, op);
10373 }
10374
10375
10376
10377
10378
10379
10380
10381
10382
10383
10384
10385
10386
10387
10388
10389
10390 int
10391 move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos, int op)
10392 {
10393 enum move_it_result skip, skip2 = MOVE_X_REACHED;
10394 int line_height, line_start_x = 0, reached = 0;
10395 int max_current_x = 0;
10396 void *backup_data = NULL;
10397 ptrdiff_t orig_charpos = -1;
10398 enum it_method orig_method = NUM_IT_METHODS;
10399
10400 for (;;)
10401 {
10402 orig_charpos = IT_CHARPOS (*it);
10403 orig_method = it->method;
10404 if (op & MOVE_TO_VPOS)
10405 {
10406
10407
10408 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
10409 {
10410 if (it->vpos == to_vpos)
10411 {
10412 reached = 1;
10413 break;
10414 }
10415 else
10416 skip = move_it_in_display_line_to (it, -1, -1, 0);
10417 }
10418 else
10419 {
10420
10421
10422 if (it->vpos == to_vpos)
10423 {
10424 reached = 2;
10425 break;
10426 }
10427
10428 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10429
10430 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
10431 {
10432 reached = 3;
10433 break;
10434 }
10435 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
10436 {
10437
10438 skip = move_it_in_display_line_to (it, to_charpos,
10439 -1, MOVE_TO_POS);
10440 if (skip == MOVE_POS_MATCH_OR_ZV)
10441 {
10442 reached = 4;
10443 break;
10444 }
10445 }
10446 }
10447 }
10448 else if (op & MOVE_TO_Y)
10449 {
10450 struct it it_backup;
10451
10452 if (it->line_wrap == WORD_WRAP)
10453 SAVE_IT (it_backup, *it, backup_data);
10454
10455
10456
10457
10458
10459
10460
10461
10462
10463
10464
10465
10466
10467 skip = move_it_in_display_line_to
10468 (it, to_charpos, ((op & MOVE_TO_X) ? to_x : 0),
10469 (MOVE_TO_X | (op & MOVE_TO_POS)));
10470
10471
10472 if (skip == MOVE_POS_MATCH_OR_ZV)
10473 reached = 5;
10474 else if (skip == MOVE_X_REACHED)
10475 {
10476
10477
10478
10479
10480 line_height = it->max_ascent + it->max_descent;
10481 if (to_y >= it->current_y
10482 && to_y < it->current_y + line_height)
10483 {
10484 reached = 6;
10485 break;
10486 }
10487 SAVE_IT (it_backup, *it, backup_data);
10488 move_trace ("move_it: from %td\n", IT_CHARPOS (*it));
10489 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
10490 op & MOVE_TO_POS);
10491 move_trace ("move_it: to %td\n", IT_CHARPOS (*it));
10492 line_height = it->max_ascent + it->max_descent;
10493 move_trace ("move_it: line_height = %d\n", line_height);
10494
10495 if (to_y >= it->current_y
10496 && to_y < it->current_y + line_height)
10497 {
10498
10499
10500
10501
10502
10503
10504
10505
10506 int max_ascent = it->max_ascent;
10507 int max_descent = it->max_descent;
10508
10509 RESTORE_IT (it, &it_backup, backup_data);
10510 it->max_ascent = max_ascent;
10511 it->max_descent = max_descent;
10512 reached = 6;
10513 }
10514 else
10515 {
10516 skip = skip2;
10517 if (skip == MOVE_POS_MATCH_OR_ZV)
10518 {
10519 reached = 7;
10520
10521
10522
10523
10524
10525
10526
10527 if (to_charpos > 0
10528 && IT_CHARPOS (*it) != to_charpos
10529 && ((IT_CHARPOS (it_backup) > to_charpos)
10530 == (IT_CHARPOS (*it) > to_charpos)))
10531 {
10532 int max_ascent = it->max_ascent;
10533 int max_descent = it->max_descent;
10534
10535 RESTORE_IT (it, &it_backup, backup_data);
10536 it->max_ascent = max_ascent;
10537 it->max_descent = max_descent;
10538 }
10539 }
10540 }
10541 }
10542 else
10543 {
10544
10545 line_height = it->max_ascent + it->max_descent;
10546 move_trace ("move_it: line_height = %d\n", line_height);
10547
10548 if (to_y >= it->current_y
10549 && to_y < it->current_y + line_height)
10550 {
10551 if (to_y > it->current_y)
10552 max_current_x = max (it->current_x, max_current_x);
10553
10554
10555
10556
10557
10558 if (skip == MOVE_LINE_CONTINUED
10559 && it->line_wrap == WORD_WRAP)
10560 {
10561 int prev_x = max (it->current_x - 1, 0);
10562 RESTORE_IT (it, &it_backup, backup_data);
10563 skip = move_it_in_display_line_to
10564 (it, -1, prev_x, MOVE_TO_X);
10565 }
10566
10567 reached = 6;
10568 }
10569 }
10570
10571 if (reached)
10572 {
10573 max_current_x = max (it->current_x, max_current_x);
10574 break;
10575 }
10576 }
10577 else if (BUFFERP (it->object)
10578 && (it->method == GET_FROM_BUFFER
10579 || it->method == GET_FROM_STRETCH)
10580 && IT_CHARPOS (*it) >= to_charpos
10581
10582
10583
10584
10585
10586 && !(it->bidi_p
10587 && it->bidi_it.scan_dir == -1))
10588 skip = MOVE_POS_MATCH_OR_ZV;
10589 else
10590 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
10591
10592 switch (skip)
10593 {
10594 case MOVE_POS_MATCH_OR_ZV:
10595 max_current_x = max (it->current_x, max_current_x);
10596 reached = 8;
10597 goto out;
10598
10599 case MOVE_NEWLINE_OR_CR:
10600 max_current_x = max (it->current_x, max_current_x);
10601 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10602 it->override_ascent = -1;
10603 set_iterator_to_next (it, true);
10604 it->continuation_lines_width = 0;
10605 break;
10606
10607 case MOVE_LINE_TRUNCATED:
10608 max_current_x = it->last_visible_x;
10609 it->continuation_lines_width = 0;
10610 reseat_at_next_visible_line_start (it, false);
10611 if ((op & MOVE_TO_POS) != 0
10612 && (IT_CHARPOS (*it) > to_charpos
10613 || (IT_CHARPOS (*it) == to_charpos
10614
10615
10616 && to_charpos == ZV
10617 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n')
10618
10619
10620
10621 && (it->sp == 0
10622 || (STRINGP (it->string)
10623 && (it->current.overlay_string_index < 0
10624 || (it->current.overlay_string_index >= 0
10625 && it->current.overlay_string_index
10626 >= it->n_overlay_strings - 1))
10627 && IT_STRING_CHARPOS (*it) >= it->end_charpos)))))
10628 {
10629 reached = 9;
10630 goto out;
10631 }
10632 break;
10633
10634 case MOVE_LINE_CONTINUED:
10635 max_current_x = it->last_visible_x;
10636
10637
10638
10639
10640 if (it->c == '\t')
10641 {
10642 it->continuation_lines_width += it->last_visible_x;
10643
10644
10645
10646 if (it->current_x != it->last_visible_x
10647 && (op & MOVE_TO_VPOS)
10648 && !(op & (MOVE_TO_X | MOVE_TO_POS)))
10649 {
10650 line_start_x = it->current_x + it->pixel_width
10651 - it->last_visible_x;
10652 if (FRAME_WINDOW_P (it->f))
10653 {
10654 struct face *face = FACE_FROM_ID (it->f, it->face_id);
10655 struct font *face_font = face->font;
10656
10657
10658
10659
10660
10661
10662
10663 eassert (face_font);
10664 if (face_font)
10665 {
10666 if (line_start_x < face_font->space_width)
10667 line_start_x
10668 += it->tab_width * face_font->space_width;
10669 }
10670 }
10671 set_iterator_to_next (it, false);
10672 }
10673 }
10674 else
10675 {
10676
10677
10678
10679
10680
10681
10682
10683
10684 if (IT_CHARPOS (*it) == orig_charpos
10685 && it->method == orig_method
10686 && orig_method == GET_FROM_BUFFER)
10687 set_iterator_to_next (it, false);
10688 it->continuation_lines_width += it->current_x;
10689 }
10690 break;
10691
10692 default:
10693 emacs_abort ();
10694 }
10695
10696
10697 it->current_x = line_start_x;
10698 line_start_x = 0;
10699 it->hpos = 0;
10700 it->line_number_produced_p = false;
10701 it->current_y += it->max_ascent + it->max_descent;
10702 ++it->vpos;
10703 last_height = it->max_ascent + it->max_descent;
10704 it->max_ascent = it->max_descent = 0;
10705 }
10706
10707 out:
10708
10709
10710
10711
10712
10713
10714 if (!FRAME_WINDOW_P (it->f)
10715 && op & MOVE_TO_POS
10716 && IT_CHARPOS (*it) == to_charpos
10717 && it->what == IT_CHARACTER
10718 && it->nglyphs > 1
10719 && it->line_wrap == WINDOW_WRAP
10720 && it->current_x == it->last_visible_x - 1
10721 && it->c != '\n'
10722 && it->c != '\t'
10723 && it->w->window_end_valid
10724 && it->vpos < it->w->window_end_vpos)
10725 {
10726 it->continuation_lines_width += it->current_x;
10727 it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
10728 it->current_y += it->max_ascent + it->max_descent;
10729 ++it->vpos;
10730 last_height = it->max_ascent + it->max_descent;
10731 }
10732
10733 if (backup_data)
10734 bidi_unshelve_cache (backup_data, true);
10735
10736 move_trace ("move_it_to: reached %d\n", reached);
10737
10738 return max_current_x;
10739 }
10740
10741
10742
10743
10744
10745
10746
10747
10748
10749
10750
10751 void
10752 move_it_vertically_backward (struct it *it, int dy)
10753 {
10754 int nlines, h;
10755 struct it it2, it3;
10756 void *it2data = NULL, *it3data = NULL;
10757 ptrdiff_t start_pos;
10758 int nchars_per_row
10759 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
10760 ptrdiff_t pos_limit;
10761
10762 move_further_back:
10763 eassert (dy >= 0);
10764
10765 start_pos = IT_CHARPOS (*it);
10766
10767
10768 nlines = max (1, dy / default_line_pixel_height (it->w));
10769 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
10770 pos_limit = BEGV;
10771 else
10772 pos_limit = max (start_pos - nlines * nchars_per_row, BEGV);
10773
10774
10775
10776
10777 while (nlines-- && IT_CHARPOS (*it) > pos_limit)
10778 back_to_previous_visible_line_start (it);
10779
10780
10781
10782
10783
10784 reseat_1 (it, it->current.pos, true);
10785
10786
10787 it->current_x = it->hpos = 0;
10788
10789 it->continuation_lines_width = 0;
10790
10791
10792
10793
10794
10795 SAVE_IT (it2, *it, it2data);
10796 it2.max_ascent = it2.max_descent = 0;
10797 do
10798 {
10799 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
10800 MOVE_TO_POS | MOVE_TO_VPOS);
10801 }
10802 while (!(IT_POS_VALID_AFTER_MOVE_P (&it2)
10803
10804
10805
10806
10807
10808
10809 || (it2.method == GET_FROM_STRING
10810 && IT_CHARPOS (it2) == start_pos
10811 && SREF (it2.string, IT_STRING_BYTEPOS (it2) - 1) == '\n')));
10812 eassert (IT_CHARPOS (*it) >= BEGV);
10813 SAVE_IT (it3, it2, it3data);
10814
10815 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
10816 eassert (IT_CHARPOS (*it) >= BEGV);
10817
10818
10819 h = it2.current_y - it->current_y;
10820
10821 nlines = it2.vpos - it->vpos;
10822
10823
10824
10825 it->vpos -= nlines;
10826 it->current_y -= h;
10827
10828 if (dy == 0)
10829 {
10830
10831
10832
10833 RESTORE_IT (it, it, it2data);
10834 if (nlines > 0)
10835 move_it_by_lines (it, nlines);
10836
10837
10838
10839
10840
10841
10842 if (it->bidi_p
10843 && !it->continuation_lines_width
10844 && !STRINGP (it->string)
10845 && IT_CHARPOS (*it) > BEGV
10846 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10847 {
10848 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
10849
10850 dec_both (&cp, &bp);
10851 SET_WITH_NARROWED_BEGV (it, cp,
10852 find_newline_no_quit (cp, bp, -1, NULL),
10853 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
10854 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
10855 }
10856 bidi_unshelve_cache (it3data, true);
10857 }
10858 else
10859 {
10860
10861
10862 int target_y = it->current_y + h - dy;
10863 int y0 = it3.current_y;
10864 int y1;
10865 int line_height;
10866
10867 RESTORE_IT (&it3, &it3, it3data);
10868 y1 = line_bottom_y (&it3);
10869 line_height = y1 - y0;
10870 RESTORE_IT (it, it, it2data);
10871
10872
10873 if (target_y < it->current_y
10874
10875
10876
10877
10878 && (it->current_y - target_y
10879 > min (window_box_height (it->w), line_height * 2 / 3))
10880 && IT_CHARPOS (*it) > BEGV)
10881 {
10882 move_trace (" not far enough -> move_vert %d\n",
10883 target_y - it->current_y);
10884 dy = it->current_y - target_y;
10885 goto move_further_back;
10886 }
10887 else if (target_y >= it->current_y + line_height
10888 && IT_CHARPOS (*it) < ZV)
10889 {
10890
10891
10892
10893
10894
10895
10896
10897
10898 if (!FRAME_WINDOW_P (it->f))
10899 move_it_vertically (it, target_y - it->current_y);
10900 else
10901 {
10902 struct text_pos last_pos;
10903 int last_y, last_vpos;
10904 do
10905 {
10906 last_pos = it->current.pos;
10907 last_y = it->current_y;
10908 last_vpos = it->vpos;
10909 move_it_by_lines (it, 1);
10910 }
10911 while (target_y > it->current_y && IT_CHARPOS (*it) < ZV);
10912 if (it->current_y > target_y)
10913 {
10914 reseat (it, last_pos, true);
10915 it->current_y = last_y;
10916 it->vpos = last_vpos;
10917 }
10918 }
10919 }
10920 }
10921 }
10922
10923
10924
10925
10926
10927
10928 void
10929 move_it_vertically (struct it *it, int dy)
10930 {
10931 if (dy <= 0)
10932 move_it_vertically_backward (it, -dy);
10933 else
10934 {
10935 move_trace ("move_it_v: from %td, %d\n", IT_CHARPOS (*it), dy);
10936 move_it_to (it, ZV, -1, it->current_y + dy, -1,
10937 MOVE_TO_POS | MOVE_TO_Y);
10938 move_trace ("move_it_v: to %td\n", IT_CHARPOS (*it));
10939
10940
10941
10942 if (IT_CHARPOS (*it) == ZV
10943 && ZV > BEGV
10944 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10945 move_it_by_lines (it, 0);
10946 }
10947 }
10948
10949
10950
10951
10952 void
10953 move_it_past_eol (struct it *it)
10954 {
10955 enum move_it_result rc;
10956
10957 rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
10958 if (rc == MOVE_NEWLINE_OR_CR)
10959 set_iterator_to_next (it, false);
10960 }
10961
10962
10963
10964
10965
10966
10967
10968
10969
10970
10971 void
10972 move_it_by_lines (struct it *it, ptrdiff_t dvpos)
10973 {
10974
10975
10976
10977
10978
10979
10980
10981
10982
10983
10984
10985
10986
10987
10988
10989
10990
10991 if (dvpos == 0)
10992 {
10993
10994 move_it_vertically_backward (it, 0);
10995
10996 last_height = 0;
10997 }
10998 else if (dvpos > 0)
10999 {
11000 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
11001 if (!IT_POS_VALID_AFTER_MOVE_P (it))
11002 {
11003
11004
11005
11006
11007
11008
11009
11010
11011
11012
11013 move_it_to (it, IT_CHARPOS (*it) + it->string_from_display_prop_p,
11014 -1, -1, -1, MOVE_TO_POS);
11015 }
11016 }
11017 else
11018 {
11019 struct it it2;
11020 void *it2data = NULL;
11021 ptrdiff_t start_charpos, orig_charpos, i;
11022 int nchars_per_row
11023 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
11024 bool hit_pos_limit = false;
11025 ptrdiff_t pos_limit;
11026
11027
11028
11029
11030 dvpos += it->vpos;
11031 orig_charpos = IT_CHARPOS (*it);
11032 move_it_vertically_backward (it, 0);
11033 dvpos -= it->vpos;
11034
11035
11036
11037 start_charpos = IT_CHARPOS (*it);
11038 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
11039 pos_limit = BEGV;
11040 else
11041 pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
11042
11043 for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
11044 back_to_previous_visible_line_start (it);
11045 if (i > 0 && IT_CHARPOS (*it) <= pos_limit)
11046 hit_pos_limit = true;
11047 reseat (it, it->current.pos, true);
11048
11049
11050 while (!IT_POS_VALID_AFTER_MOVE_P (it))
11051 {
11052
11053 dvpos += it->vpos;
11054 move_it_vertically_backward (it, 0);
11055 dvpos -= it->vpos;
11056 if (IT_POS_VALID_AFTER_MOVE_P (it))
11057 break;
11058
11059
11060 back_to_previous_visible_line_start (it);
11061 reseat (it, it->current.pos, true);
11062 dvpos--;
11063 }
11064
11065 it->current_x = it->hpos = 0;
11066
11067
11068
11069 SAVE_IT (it2, *it, it2data);
11070 it2.vpos = it2.current_y = 0;
11071 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
11072 it->vpos -= it2.vpos;
11073 it->current_y -= it2.current_y;
11074 it->current_x = it->hpos = 0;
11075
11076
11077 if (it2.vpos > -dvpos)
11078 {
11079 int delta = it2.vpos + dvpos;
11080
11081 RESTORE_IT (&it2, &it2, it2data);
11082 SAVE_IT (it2, *it, it2data);
11083 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
11084
11085
11086 if (it->vpos - it2.vpos > delta || IT_CHARPOS (*it) == orig_charpos)
11087 RESTORE_IT (it, &it2, it2data);
11088 else
11089 bidi_unshelve_cache (it2data, true);
11090 }
11091 else if (hit_pos_limit && pos_limit > BEGV
11092 && dvpos < 0 && it2.vpos < -dvpos)
11093 {
11094
11095
11096
11097
11098
11099
11100
11101
11102 dvpos += it2.vpos;
11103 RESTORE_IT (it, it, it2data);
11104 for (i = -dvpos; i > 0; --i)
11105 {
11106 back_to_previous_visible_line_start (it);
11107 it->vpos--;
11108 }
11109 reseat_1 (it, it->current.pos, true);
11110 }
11111 else
11112 RESTORE_IT (it, it, it2data);
11113 }
11114 }
11115
11116 int
11117 partial_line_height (struct it *it_origin)
11118 {
11119
11120
11121
11122
11123
11124 if (XBUFFER (it_origin->w->contents)->long_line_optimizations_p
11125 && it_origin->line_wrap == TRUNCATE)
11126 return 0;
11127
11128 int partial_height;
11129 void *it_data = NULL;
11130 struct it it;
11131 SAVE_IT (it, *it_origin, it_data);
11132 move_it_to (&it, ZV, -1, it.last_visible_y, -1,
11133 MOVE_TO_POS | MOVE_TO_Y);
11134 if (it.what == IT_EOB)
11135 {
11136 int vis_height = it.last_visible_y - it.current_y;
11137 int height = it.ascent + it.descent;
11138 partial_height = (vis_height < height) ? vis_height : 0;
11139 }
11140 else
11141 {
11142 int last_line_y = it.current_y;
11143 move_it_by_lines (&it, 1);
11144 partial_height = (it.current_y > it.last_visible_y)
11145 ? it.last_visible_y - last_line_y : 0;
11146 }
11147 RESTORE_IT (&it, &it, it_data);
11148 return partial_height;
11149 }
11150
11151
11152
11153
11154
11155
11156
11157
11158
11159
11160
11161
11162 static enum move_it_result
11163 fast_move_it_horizontally (struct it *it, ptrdiff_t nchars)
11164 {
11165 ptrdiff_t nl_bytepos;
11166 ptrdiff_t nl_pos = find_newline_no_quit (IT_CHARPOS (*it), IT_BYTEPOS (*it),
11167 1, &nl_bytepos);
11168 struct text_pos new_pos;
11169 enum move_it_result move_result;
11170
11171 if (nl_pos - IT_CHARPOS (*it) > nchars)
11172 {
11173 SET_TEXT_POS (new_pos,
11174 IT_CHARPOS (*it) + nchars,
11175 CHAR_TO_BYTE (IT_CHARPOS (*it) + nchars));
11176 move_result = MOVE_X_REACHED;
11177 }
11178 else
11179 {
11180 if (nl_bytepos < ZV_BYTE
11181 || (nl_bytepos > BEGV_BYTE
11182 && FETCH_BYTE (nl_bytepos - 1) == '\n'))
11183 {
11184 nl_pos--;
11185 nl_bytepos--;
11186 move_result = MOVE_NEWLINE_OR_CR;
11187 }
11188 else
11189 move_result = MOVE_POS_MATCH_OR_ZV;
11190 SET_TEXT_POS (new_pos, nl_pos, nl_bytepos);
11191 }
11192 reseat (it, new_pos, false);
11193 return move_result;
11194 }
11195
11196
11197
11198 bool
11199 in_display_vector_p (struct it *it)
11200 {
11201 return (it->method == GET_FROM_DISPLAY_VECTOR
11202 && it->current.dpvec_index > 0
11203 && it->dpvec + it->current.dpvec_index != it->dpend);
11204 }
11205
11206
11207
11208
11209
11210 static Lisp_Object
11211 window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
11212 Lisp_Object x_limit, Lisp_Object y_limit,
11213 Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11214 {
11215 struct window *w = decode_live_window (window);
11216 struct it it;
11217 ptrdiff_t start, end, bpos;
11218 struct text_pos startp;
11219 void *itdata = NULL;
11220 int c, max_x = 0, max_y = 0, x = 0, y = 0, vertical_offset = 0, doff = 0;
11221
11222 if (NILP (from))
11223 {
11224 start = BEGV;
11225 bpos = BEGV_BYTE;
11226 }
11227 else if (EQ (from, Qt))
11228 {
11229 start = BEGV;
11230 bpos = BEGV_BYTE;
11231 while (bpos < ZV_BYTE)
11232 {
11233 c = FETCH_BYTE (bpos);
11234 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11235 break;
11236 inc_both (&start, &bpos);
11237 }
11238 while (bpos > BEGV_BYTE)
11239 {
11240 dec_both (&start, &bpos);
11241 c = FETCH_BYTE (bpos);
11242 if (!(c == ' ' || c == '\t'))
11243 break;
11244 }
11245 }
11246 else if (CONSP (from))
11247 {
11248 start = clip_to_bounds (BEGV, fix_position (XCAR (from)), ZV);
11249 bpos = CHAR_TO_BYTE (start);
11250 CHECK_FIXNUM (XCDR (from));
11251 vertical_offset = XFIXNUM (XCDR (from));
11252 }
11253 else
11254 {
11255 start = clip_to_bounds (BEGV, fix_position (from), ZV);
11256 bpos = CHAR_TO_BYTE (start);
11257 }
11258
11259 SET_TEXT_POS (startp, start, bpos);
11260
11261 if (NILP (to))
11262 end = ZV;
11263 else if (EQ (to, Qt))
11264 {
11265 end = ZV;
11266 bpos = ZV_BYTE;
11267 while (bpos > BEGV_BYTE)
11268 {
11269 dec_both (&end, &bpos);
11270 c = FETCH_BYTE (bpos);
11271 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11272 {
11273 inc_both (&end, &bpos);
11274 break;
11275 }
11276 }
11277 while (bpos < ZV_BYTE)
11278 {
11279 c = fetch_char_advance (&end, &bpos);
11280 if (!(c == ' ' || c == '\t'))
11281 break;
11282 }
11283 }
11284 else
11285 end = clip_to_bounds (start, fix_position (to), ZV);
11286
11287 if (RANGED_FIXNUMP (0, x_limit, INT_MAX))
11288 max_x = XFIXNUM (x_limit);
11289 else if (!NILP (x_limit))
11290 max_x = INT_MAX;
11291
11292 if (NILP (y_limit))
11293 max_y = INT_MAX;
11294 else if (RANGED_FIXNUMP (0, y_limit, INT_MAX))
11295 max_y = XFIXNUM (y_limit);
11296
11297 itdata = bidi_shelve_cache ();
11298
11299 start_display (&it, w, startp);
11300
11301 int start_y = it.current_y;
11302
11303
11304
11305
11306
11307
11308
11309 it.bidi_p = false;
11310
11311 int start_x;
11312 if (vertical_offset != 0)
11313 {
11314 int last_y;
11315 it.current_y = 0;
11316
11317 move_it_by_lines (&it, 0);
11318
11319
11320
11321
11322
11323 if (vertical_offset < 0)
11324 {
11325 while (it.current_y > vertical_offset)
11326 {
11327 last_y = it.current_y;
11328 move_it_vertically_backward (&it,
11329 (abs (vertical_offset)
11330 + it.current_y));
11331
11332 if (it.current_y == last_y)
11333 break;
11334 }
11335 }
11336 else
11337 {
11338 move_it_vertically (&it, vertical_offset);
11339 }
11340
11341 it.current_y = (WINDOW_TAB_LINE_HEIGHT (w)
11342 + WINDOW_HEADER_LINE_HEIGHT (w));
11343 start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV);
11344 start_y = it.current_y;
11345 start_x = it.current_x;
11346 }
11347 else
11348 {
11349
11350
11351
11352 reseat_at_previous_visible_line_start (&it);
11353 it.current_x = it.hpos = 0;
11354 if (IT_CHARPOS (it) != start)
11355 {
11356 void *it1data = NULL;
11357 struct it it1;
11358
11359 SAVE_IT (it1, it, it1data);
11360 move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
11361
11362
11363
11364
11365
11366 if (IT_CHARPOS (it) > start && start > BEGV)
11367 {
11368 ptrdiff_t it1pos = IT_CHARPOS (it1);
11369 int it1_x = it1.current_x;
11370
11371 RESTORE_IT (&it, &it1, it1data);
11372
11373
11374
11375
11376
11377 if (start - 1 > it1pos)
11378 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11379 else
11380 move_it_in_display_line (&it, start, it1_x + 1,
11381 MOVE_TO_POS | MOVE_TO_X);
11382 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11383 start_x = it.current_x;
11384
11385
11386
11387 if (IT_CHARPOS (it) == start - 1)
11388 start_x += it.pixel_width;
11389 }
11390 else
11391 {
11392 start_x = it.current_x;
11393 bidi_unshelve_cache (it1data, true);
11394 }
11395 }
11396 else
11397 start_x = it.current_x;
11398 }
11399
11400
11401 int move_op = MOVE_TO_POS | MOVE_TO_Y;
11402 int to_x = -1;
11403 it.current_y = start_y;
11404
11405
11406 if (FETCH_BYTE (start) == '\n')
11407 it.current_x = 0;
11408 if (!NILP (x_limit))
11409 {
11410 it.last_visible_x = max_x;
11411
11412
11413
11414 move_op |= MOVE_TO_X;
11415 to_x = INT_MAX;
11416 }
11417
11418 void *it2data = NULL;
11419 struct it it2;
11420 SAVE_IT (it2, it, it2data);
11421
11422 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11423
11424
11425
11426
11427
11428 if (IT_CHARPOS (it) > end)
11429 {
11430 end--;
11431 RESTORE_IT (&it, &it2, it2data);
11432 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11433
11434
11435
11436 if (IT_CHARPOS (it) == end)
11437 {
11438 x += it.pixel_width;
11439
11440
11441 if (!NILP (ignore_line_at_end))
11442 doff = (max (it.max_ascent, it.ascent)
11443 + max (it.max_descent, it.descent));
11444 else
11445 {
11446 it.max_ascent = max (it.max_ascent, it.ascent);
11447 it.max_descent = max (it.max_descent, it.descent);
11448 }
11449 }
11450 }
11451 else
11452 bidi_unshelve_cache (it2data, true);
11453
11454 if (!NILP (x_limit))
11455 {
11456
11457 if (x > max_x)
11458 x = max_x;
11459 }
11460
11461
11462
11463
11464 if (it.current_y > start_y)
11465 start_x = 0;
11466
11467
11468
11469 if (!NILP (ignore_line_at_end))
11470 y = (it.current_y + doff
11471 - WINDOW_TAB_LINE_HEIGHT (w)
11472 - WINDOW_HEADER_LINE_HEIGHT (w));
11473 else
11474 y = (it.current_y + it.max_ascent + it.max_descent + doff
11475 - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w));
11476
11477
11478 if (y > max_y)
11479 y = max_y;
11480
11481 if ((EQ (mode_lines, Qtab_line) || EQ (mode_lines, Qt))
11482 && window_wants_tab_line (w))
11483
11484 {
11485 Lisp_Object window_tab_line_format
11486 = window_parameter (w, Qtab_line_format);
11487
11488 y = y + display_mode_line (w, TAB_LINE_FACE_ID,
11489 NILP (window_tab_line_format)
11490 ? BVAR (current_buffer, tab_line_format)
11491 : window_tab_line_format);
11492 }
11493
11494 if ((EQ (mode_lines, Qheader_line) || EQ (mode_lines, Qt))
11495 && window_wants_header_line (w))
11496 {
11497 Lisp_Object window_header_line_format
11498 = window_parameter (w, Qheader_line_format);
11499
11500 y = y + display_mode_line (w, HEADER_LINE_FACE_ID,
11501 NILP (window_header_line_format)
11502 ? BVAR (current_buffer, header_line_format)
11503 : window_header_line_format);
11504 }
11505
11506 if ((EQ (mode_lines, Qmode_line) || EQ (mode_lines, Qt))
11507 && window_wants_mode_line (w))
11508 {
11509 Lisp_Object window_mode_line_format
11510 = window_parameter (w, Qmode_line_format);
11511
11512 y = y + display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
11513 NILP (window_mode_line_format)
11514 ? BVAR (current_buffer, mode_line_format)
11515 : window_mode_line_format);
11516 }
11517
11518 bidi_unshelve_cache (itdata, false);
11519
11520 return (!vertical_offset
11521 ? Fcons (make_fixnum (x - start_x), make_fixnum (y))
11522 : list3i (x - start_x, y, start));
11523 }
11524
11525 DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 0,
11526 doc:
11527
11528
11529
11530
11531
11532
11533
11534
11535
11536
11537
11538
11539
11540
11541
11542
11543
11544
11545
11546
11547
11548
11549
11550
11551
11552
11553
11554
11555
11556
11557
11558
11559
11560
11561
11562
11563
11564
11565
11566
11567
11568
11569
11570
11571
11572
11573
11574
11575
11576
11577
11578
11579
11580
11581 )
11582 (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit,
11583 Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11584 {
11585 struct window *w = decode_live_window (window);
11586 struct buffer *b = XBUFFER (w->contents);
11587 struct buffer *old_b = NULL;
11588 Lisp_Object value;
11589
11590 if (b != current_buffer)
11591 {
11592 old_b = current_buffer;
11593 set_buffer_internal_1 (b);
11594 }
11595
11596 value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines,
11597 ignore_line_at_end);
11598
11599 if (old_b)
11600 set_buffer_internal_1 (old_b);
11601
11602 return value;
11603 }
11604
11605 DEFUN ("buffer-text-pixel-size", Fbuffer_text_pixel_size, Sbuffer_text_pixel_size, 0, 4, 0,
11606 doc:
11607
11608
11609
11610
11611
11612
11613
11614
11615
11616
11617
11618
11619 )
11620 (Lisp_Object buffer_or_name, Lisp_Object window, Lisp_Object x_limit,
11621 Lisp_Object y_limit)
11622 {
11623 struct window *w = decode_live_window (window);
11624 struct buffer *b = (NILP (buffer_or_name)
11625 ? current_buffer
11626 : XBUFFER (Fget_buffer (buffer_or_name)));
11627 Lisp_Object buffer, value;
11628 specpdl_ref count = SPECPDL_INDEX ();
11629
11630 XSETBUFFER (buffer, b);
11631
11632
11633
11634
11635 record_unwind_protect (unwind_with_echo_area_buffer,
11636 with_echo_area_buffer_unwind_data (w));
11637
11638 set_buffer_internal_1 (b);
11639
11640 if (!EQ (buffer, w->contents))
11641 {
11642 wset_buffer (w, buffer);
11643 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
11644 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
11645 }
11646
11647 value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil,
11648 Qnil);
11649
11650 unbind_to (count, Qnil);
11651
11652 return value;
11653 }
11654
11655
11656 DEFUN ("display--line-is-continued-p", Fdisplay__line_is_continued_p,
11657 Sdisplay__line_is_continued_p, 0, 0, 0,
11658 doc: )
11659 (void)
11660 {
11661 struct buffer *oldb = current_buffer;
11662 struct window *w = XWINDOW (selected_window);
11663 enum move_it_result rc = MOVE_POS_MATCH_OR_ZV;
11664
11665 set_buffer_internal_1 (XBUFFER (w->contents));
11666
11667 if (PT < ZV)
11668 {
11669 struct text_pos startpos;
11670 struct it it;
11671 void *itdata;
11672
11673
11674 Lisp_Object opoint = Fpoint_marker ();
11675
11676
11677
11678 Fvertical_motion (make_fixnum (0), selected_window, Qnil);
11679 SET_TEXT_POS (startpos, PT, PT_BYTE);
11680 itdata = bidi_shelve_cache ();
11681 start_display (&it, w, startpos);
11682
11683 if (it.line_wrap != TRUNCATE)
11684 {
11685 it.glyph_row = NULL;
11686 rc = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
11687 }
11688 SET_PT_BOTH (marker_position (opoint), marker_byte_position (opoint));
11689 bidi_unshelve_cache (itdata, false);
11690 }
11691 set_buffer_internal_1 (oldb);
11692
11693 return rc == MOVE_LINE_CONTINUED ? Qt : Qnil;
11694 }
11695
11696
11697
11698
11699
11700
11701
11702
11703 static ptrdiff_t
11704 format_nargs (char const *format)
11705 {
11706 ptrdiff_t nargs = 0;
11707 for (char const *p = format; (p = strchr (p, '%')); p++)
11708 if (p[1] == '%')
11709 p++;
11710 else
11711 nargs++;
11712 return nargs;
11713 }
11714
11715
11716
11717
11718 void
11719 add_to_log (const char *format, ...)
11720 {
11721 va_list ap;
11722 va_start (ap, format);
11723 vadd_to_log (format, ap);
11724 va_end (ap);
11725 }
11726
11727 void
11728 vadd_to_log (char const *format, va_list ap)
11729 {
11730 ptrdiff_t form_nargs = format_nargs (format);
11731 ptrdiff_t nargs = 1 + form_nargs;
11732 Lisp_Object args[10];
11733 eassert (nargs <= ARRAYELTS (args));
11734 AUTO_STRING (args0, format);
11735 args[0] = args0;
11736 for (ptrdiff_t i = 1; i <= nargs; i++)
11737 args[i] = va_arg (ap, Lisp_Object);
11738 Lisp_Object msg = Qnil;
11739 msg = Fformat_message (nargs, args);
11740
11741 ptrdiff_t len = SBYTES (msg) + 1;
11742 USE_SAFE_ALLOCA;
11743 char *buffer = SAFE_ALLOCA (len);
11744 memcpy (buffer, SDATA (msg), len);
11745
11746 message_dolog (buffer, len - 1, true, STRING_MULTIBYTE (msg));
11747 SAFE_FREE ();
11748 }
11749
11750
11751
11752
11753 void
11754 message_log_maybe_newline (void)
11755 {
11756 if (message_log_need_newline)
11757 message_dolog ("", 0, true, false);
11758 }
11759
11760
11761
11762
11763
11764
11765
11766
11767
11768
11769
11770 void
11771 message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
11772 {
11773 const unsigned char *msg = (const unsigned char *) m;
11774
11775 if (!NILP (Vmemory_full))
11776 return;
11777
11778 if (!NILP (Vmessage_log_max))
11779 {
11780 struct buffer *oldbuf;
11781 Lisp_Object oldpoint, oldbegv, oldzv;
11782 int old_windows_or_buffers_changed = windows_or_buffers_changed;
11783 ptrdiff_t point_at_end = 0;
11784 ptrdiff_t zv_at_end = 0;
11785 Lisp_Object old_deactivate_mark;
11786
11787 old_deactivate_mark = Vdeactivate_mark;
11788 oldbuf = current_buffer;
11789
11790
11791
11792 if (! STRINGP (Vmessages_buffer_name))
11793 Vmessages_buffer_name = build_string ("*Messages*");
11794
11795
11796 bool newbuffer = NILP (Fget_buffer (Vmessages_buffer_name));
11797 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name, Qnil));
11798 if (newbuffer
11799 && !NILP (Ffboundp (intern ("messages-buffer-mode"))))
11800 call0 (intern ("messages-buffer-mode"));
11801
11802 bset_undo_list (current_buffer, Qt);
11803 bset_cache_long_scans (current_buffer, Qnil);
11804
11805 oldpoint = message_dolog_marker1;
11806 set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);
11807 oldbegv = message_dolog_marker2;
11808 set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE);
11809 oldzv = message_dolog_marker3;
11810 set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE);
11811
11812 if (PT == Z)
11813 point_at_end = 1;
11814 if (ZV == Z)
11815 zv_at_end = 1;
11816
11817 BEGV = BEG;
11818 BEGV_BYTE = BEG_BYTE;
11819 ZV = Z;
11820 ZV_BYTE = Z_BYTE;
11821 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11822
11823
11824
11825 if (multibyte
11826 && NILP (BVAR (current_buffer, enable_multibyte_characters)))
11827 {
11828
11829
11830 for (ptrdiff_t i = 0; i < nbytes; )
11831 {
11832 int char_bytes, c = check_char_and_length (msg + i, &char_bytes);
11833 char work = CHAR_TO_BYTE8 (c);
11834 insert_1_both (&work, 1, 1, true, false, false);
11835 i += char_bytes;
11836 }
11837 }
11838 else if (! multibyte
11839 && ! NILP (BVAR (current_buffer, enable_multibyte_characters)))
11840 {
11841
11842
11843 for (ptrdiff_t i = 0; i < nbytes; i++)
11844 {
11845 int c = make_char_multibyte (msg[i]);
11846 unsigned char str[MAX_MULTIBYTE_LENGTH];
11847 int char_bytes = CHAR_STRING (c, str);
11848 insert_1_both ((char *) str, 1, char_bytes, true, false, false);
11849 }
11850 }
11851 else if (nbytes)
11852 insert_1_both (m, chars_in_text (msg, nbytes), nbytes,
11853 true, false, false);
11854
11855 if (nlflag)
11856 {
11857 ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte;
11858 intmax_t dups;
11859
11860
11861
11862
11863
11864 specpdl_ref count = SPECPDL_INDEX ();
11865 specbind (Qinhibit_modification_hooks, Qt);
11866
11867 insert_1_both ("\n", 1, 1, true, false, false);
11868
11869 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, false);
11870 this_bol = PT;
11871 this_bol_byte = PT_BYTE;
11872
11873
11874
11875 if (this_bol > BEG)
11876 {
11877 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, false);
11878 prev_bol = PT;
11879 prev_bol_byte = PT_BYTE;
11880
11881 dups = message_log_check_duplicate (prev_bol_byte,
11882 this_bol_byte);
11883 if (dups)
11884 {
11885 del_range_both (prev_bol, prev_bol_byte,
11886 this_bol, this_bol_byte, false);
11887 if (dups > 1)
11888 {
11889 char dupstr[sizeof " [ times]"
11890 + INT_STRLEN_BOUND (dups)];
11891
11892
11893
11894 int duplen = sprintf (dupstr, " [%"PRIdMAX" times]",
11895 dups);
11896 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
11897 insert_1_both (dupstr, duplen, duplen,
11898 true, false, true);
11899 }
11900 }
11901 }
11902
11903
11904
11905
11906
11907 if (FIXNATP (Vmessage_log_max))
11908 {
11909 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
11910 -XFIXNAT (Vmessage_log_max) - 1, false);
11911 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, false);
11912 }
11913
11914 unbind_to (count, Qnil);
11915 }
11916 BEGV = marker_position (oldbegv);
11917 BEGV_BYTE = marker_byte_position (oldbegv);
11918
11919 if (zv_at_end)
11920 {
11921 ZV = Z;
11922 ZV_BYTE = Z_BYTE;
11923 }
11924 else
11925 {
11926 ZV = marker_position (oldzv);
11927 ZV_BYTE = marker_byte_position (oldzv);
11928 }
11929
11930 if (point_at_end)
11931 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11932 else
11933
11934
11935 TEMP_SET_PT_BOTH (marker_position (oldpoint),
11936 marker_byte_position (oldpoint));
11937
11938 unchain_marker (XMARKER (oldpoint));
11939 unchain_marker (XMARKER (oldbegv));
11940 unchain_marker (XMARKER (oldzv));
11941
11942
11943
11944
11945
11946
11947
11948 windows_or_buffers_changed = old_windows_or_buffers_changed;
11949 bset_redisplay (current_buffer);
11950
11951 set_buffer_internal (oldbuf);
11952
11953 message_log_need_newline = !nlflag;
11954 Vdeactivate_mark = old_deactivate_mark;
11955 }
11956 }
11957
11958
11959
11960
11961
11962
11963
11964
11965 static intmax_t
11966 message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte)
11967 {
11968 ptrdiff_t i;
11969 ptrdiff_t len = Z_BYTE - 1 - this_bol_byte;
11970 bool seen_dots = false;
11971 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
11972 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
11973
11974 for (i = 0; i < len; i++)
11975 {
11976 if (i >= 3 && p1[i - 3] == '.' && p1[i - 2] == '.' && p1[i - 1] == '.')
11977 seen_dots = true;
11978 if (p1[i] != p2[i])
11979 return seen_dots;
11980 }
11981 p1 += len;
11982 if (*p1 == '\n')
11983 return 2;
11984 if (*p1++ == ' ' && *p1++ == '[')
11985 {
11986 char *pend;
11987 intmax_t n = strtoimax ((char *) p1, &pend, 10);
11988 if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0)
11989 return n + 1;
11990 }
11991 return 0;
11992 }
11993
11994
11995
11996
11997
11998
11999
12000
12001
12002 void
12003 message3 (Lisp_Object m)
12004 {
12005 clear_message (true, true);
12006 cancel_echoing ();
12007
12008
12009 message_log_maybe_newline ();
12010 if (STRINGP (m))
12011 {
12012 ptrdiff_t nbytes = SBYTES (m);
12013 bool multibyte = STRING_MULTIBYTE (m);
12014 char *buffer;
12015 USE_SAFE_ALLOCA;
12016 SAFE_ALLOCA_STRING (buffer, m);
12017 message_dolog (buffer, nbytes, true, multibyte);
12018 SAFE_FREE ();
12019 }
12020 if (! inhibit_message)
12021 message3_nolog (m);
12022 }
12023
12024
12025
12026 static void
12027 message_to_stderr (Lisp_Object m)
12028 {
12029 if (noninteractive_need_newline)
12030 {
12031 noninteractive_need_newline = false;
12032 errputc ('\n');
12033 }
12034 if (STRINGP (m))
12035 {
12036 Lisp_Object coding_system = Vlocale_coding_system;
12037 Lisp_Object s;
12038
12039 if (!NILP (Vcoding_system_for_write))
12040 coding_system = Vcoding_system_for_write;
12041 if (!NILP (coding_system))
12042 s = code_convert_string_norecord (m, coding_system, true);
12043 else
12044 s = m;
12045
12046 errwrite (SDATA (s), SBYTES (s));
12047 }
12048 if (STRINGP (m) || !cursor_in_echo_area)
12049 errputc ('\n');
12050 }
12051
12052
12053
12054
12055
12056
12057 void
12058 message3_nolog (Lisp_Object m)
12059 {
12060 struct frame *sf = SELECTED_FRAME ();
12061
12062 if (FRAME_INITIAL_P (sf))
12063 message_to_stderr (m);
12064
12065
12066
12067 else if (INTERACTIVE && sf->glyphs_initialized_p)
12068 {
12069
12070
12071 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
12072 Lisp_Object frame = XWINDOW (mini_window)->frame;
12073 struct frame *f = XFRAME (frame);
12074
12075 if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f))
12076 Fmake_frame_visible (frame);
12077
12078 if (STRINGP (m) && SCHARS (m) > 0)
12079 {
12080 set_message (m);
12081 if (minibuffer_auto_raise)
12082 Fraise_frame (frame);
12083
12084
12085 echo_message_buffer = Qnil;
12086 }
12087 else
12088 clear_message (true, true);
12089
12090 do_pending_window_change (false);
12091 echo_area_display (true);
12092 do_pending_window_change (false);
12093 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
12094 (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
12095 }
12096 }
12097
12098
12099
12100
12101
12102
12103
12104
12105
12106
12107 void
12108 message1 (const char *m)
12109 {
12110 message3 (m ? build_unibyte_string (m) : Qnil);
12111 }
12112
12113
12114
12115
12116 void
12117 message1_nolog (const char *m)
12118 {
12119 message3_nolog (m ? build_unibyte_string (m) : Qnil);
12120 }
12121
12122
12123
12124
12125 void
12126 message_with_string (const char *m, Lisp_Object string, bool log)
12127 {
12128 CHECK_STRING (string);
12129
12130 bool need_message;
12131 if (noninteractive)
12132 need_message = !!m;
12133 else if (!INTERACTIVE)
12134 need_message = false;
12135 else
12136 {
12137
12138
12139
12140 Lisp_Object mini_window;
12141 struct frame *f, *sf = SELECTED_FRAME ();
12142
12143
12144
12145 mini_window = FRAME_MINIBUF_WINDOW (sf);
12146 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12147
12148
12149
12150
12151 need_message = f->glyphs_initialized_p;
12152 }
12153
12154 if (need_message)
12155 {
12156 AUTO_STRING (fmt, m);
12157 Lisp_Object msg = CALLN (Fformat_message, fmt, string);
12158
12159 if (noninteractive)
12160 message_to_stderr (msg);
12161 else
12162 {
12163 if (log)
12164 message3 (msg);
12165 else
12166 message3_nolog (msg);
12167
12168
12169
12170 message_buf_print = false;
12171 }
12172 }
12173 }
12174
12175
12176
12177
12178
12179
12180
12181
12182
12183
12184
12185
12186 static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
12187 vmessage (const char *m, va_list ap)
12188 {
12189 if (noninteractive)
12190 {
12191 if (m)
12192 {
12193 if (noninteractive_need_newline)
12194 putc ('\n', stderr);
12195 noninteractive_need_newline = false;
12196 vfprintf (stderr, m, ap);
12197 if (!cursor_in_echo_area)
12198 putc ('\n', stderr);
12199 fflush (stderr);
12200 }
12201 }
12202 else if (INTERACTIVE)
12203 {
12204
12205
12206
12207 Lisp_Object mini_window;
12208 struct frame *f, *sf = SELECTED_FRAME ();
12209
12210
12211
12212 mini_window = FRAME_MINIBUF_WINDOW (sf);
12213 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12214
12215
12216
12217
12218 if (f->glyphs_initialized_p)
12219 {
12220 if (m)
12221 {
12222 ptrdiff_t len;
12223 ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
12224 USE_SAFE_ALLOCA;
12225 char *message_buf = SAFE_ALLOCA (maxsize + 1);
12226
12227 len = doprnt (message_buf, maxsize, m, 0, ap);
12228
12229 message3 (make_string (message_buf, len));
12230 SAFE_FREE ();
12231 }
12232 else
12233 message1 (0);
12234
12235
12236
12237 message_buf_print = false;
12238 }
12239 }
12240 }
12241
12242
12243 void
12244 message (const char *m, ...)
12245 {
12246 va_list ap;
12247 va_start (ap, m);
12248 vmessage (m, ap);
12249 va_end (ap);
12250 }
12251
12252
12253
12254
12255
12256
12257 void
12258 update_echo_area (void)
12259 {
12260 if (!NILP (echo_area_buffer[0]))
12261 {
12262 Lisp_Object string;
12263 string = Fcurrent_message ();
12264 message3 (string);
12265 }
12266 }
12267
12268
12269
12270
12271
12272 static void
12273 ensure_echo_area_buffers (void)
12274 {
12275 for (int i = 0; i < 2; i++)
12276 if (!BUFFERP (echo_buffer[i])
12277 || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
12278 {
12279 Lisp_Object old_buffer = echo_buffer[i];
12280 static char const name_fmt[] = " *Echo Area %d*";
12281 char name[sizeof name_fmt + INT_STRLEN_BOUND (int)];
12282 AUTO_STRING_WITH_LEN (lname, name, sprintf (name, name_fmt, i));
12283 echo_buffer[i] = Fget_buffer_create (lname, Qnil);
12284 bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil);
12285
12286
12287
12288
12289 for (int j = 0; j < 2; j++)
12290 if (EQ (old_buffer, echo_area_buffer[j]))
12291 echo_area_buffer[j] = echo_buffer[i];
12292 }
12293 }
12294
12295
12296
12297
12298
12299
12300
12301
12302
12303
12304
12305
12306
12307
12308
12309
12310
12311
12312 static bool
12313 with_echo_area_buffer (struct window *w, int which,
12314 bool (*fn) (void *, Lisp_Object),
12315 void *a1, Lisp_Object a2)
12316 {
12317 Lisp_Object buffer;
12318 bool this_one, the_other, clear_buffer_p, rc;
12319 specpdl_ref count = SPECPDL_INDEX ();
12320
12321
12322 ensure_echo_area_buffers ();
12323
12324 clear_buffer_p = false;
12325
12326 if (which == 0)
12327 this_one = false, the_other = true;
12328 else if (which > 0)
12329 this_one = true, the_other = false;
12330 else
12331 {
12332 this_one = false, the_other = true;
12333 clear_buffer_p = true;
12334
12335
12336
12337 if (!NILP (echo_area_buffer[this_one])
12338 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
12339 echo_area_buffer[this_one] = Qnil;
12340 }
12341
12342
12343
12344 if (NILP (echo_area_buffer[this_one]))
12345 {
12346 echo_area_buffer[this_one]
12347 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
12348 ? echo_buffer[the_other]
12349 : echo_buffer[this_one]);
12350 clear_buffer_p = true;
12351 }
12352
12353 buffer = echo_area_buffer[this_one];
12354
12355
12356
12357 if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
12358 cancel_echoing ();
12359
12360 record_unwind_protect (unwind_with_echo_area_buffer,
12361 with_echo_area_buffer_unwind_data (w));
12362
12363
12364
12365
12366
12367
12368
12369
12370 set_buffer_internal_1 (XBUFFER (buffer));
12371 if (w)
12372 {
12373 wset_buffer (w, buffer);
12374 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
12375 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
12376 }
12377
12378 bset_undo_list (current_buffer, Qt);
12379 bset_read_only (current_buffer, Qnil);
12380 specbind (Qinhibit_read_only, Qt);
12381 specbind (Qinhibit_modification_hooks, Qt);
12382
12383 if (clear_buffer_p && Z > BEG)
12384 del_range (BEG, Z);
12385
12386 eassert (BEGV >= BEG);
12387 eassert (ZV <= Z && ZV >= BEGV);
12388
12389 rc = fn (a1, a2);
12390
12391 eassert (BEGV >= BEG);
12392 eassert (ZV <= Z && ZV >= BEGV);
12393
12394 unbind_to (count, Qnil);
12395 return rc;
12396 }
12397
12398
12399
12400
12401
12402 static Lisp_Object
12403 with_echo_area_buffer_unwind_data (struct window *w)
12404 {
12405 int i = 0;
12406 Lisp_Object vector, tmp;
12407
12408
12409
12410 vector = Vwith_echo_area_save_vector;
12411 Vwith_echo_area_save_vector = Qnil;
12412
12413 if (NILP (vector))
12414 vector = make_nil_vector (11);
12415
12416 XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
12417 ASET (vector, i, Vdeactivate_mark); ++i;
12418 ASET (vector, i, make_fixnum (windows_or_buffers_changed)); ++i;
12419
12420 if (w)
12421 {
12422 XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
12423 ASET (vector, i, w->contents); ++i;
12424 ASET (vector, i, make_fixnum (marker_position (w->pointm))); ++i;
12425 ASET (vector, i, make_fixnum (marker_byte_position (w->pointm))); ++i;
12426 ASET (vector, i, make_fixnum (marker_position (w->old_pointm))); ++i;
12427 ASET (vector, i, make_fixnum (marker_byte_position (w->old_pointm))); ++i;
12428 ASET (vector, i, make_fixnum (marker_position (w->start))); ++i;
12429 ASET (vector, i, make_fixnum (marker_byte_position (w->start))); ++i;
12430 }
12431 else
12432 {
12433 int end = i + 8;
12434 for (; i < end; ++i)
12435 ASET (vector, i, Qnil);
12436 }
12437
12438 eassert (i == ASIZE (vector));
12439 return vector;
12440 }
12441
12442
12443
12444
12445
12446 static void
12447 unwind_with_echo_area_buffer (Lisp_Object vector)
12448 {
12449 set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
12450 Vdeactivate_mark = AREF (vector, 1);
12451 windows_or_buffers_changed = XFIXNAT (AREF (vector, 2));
12452
12453 if (WINDOWP (AREF (vector, 3)))
12454 {
12455 struct window *w;
12456 Lisp_Object buffer;
12457
12458 w = XWINDOW (AREF (vector, 3));
12459 buffer = AREF (vector, 4);
12460
12461 wset_buffer (w, buffer);
12462 set_marker_restricted_both (w->pointm, buffer,
12463 XFIXNAT (AREF (vector, 5)),
12464 XFIXNAT (AREF (vector, 6)));
12465 set_marker_restricted_both (w->old_pointm, buffer,
12466 XFIXNAT (AREF (vector, 7)),
12467 XFIXNAT (AREF (vector, 8)));
12468 set_marker_restricted_both (w->start, buffer,
12469 XFIXNAT (AREF (vector, 9)),
12470 XFIXNAT (AREF (vector, 10)));
12471 }
12472
12473 Vwith_echo_area_save_vector = vector;
12474 }
12475
12476
12477
12478
12479
12480 void
12481 setup_echo_area_for_printing (bool multibyte_p)
12482 {
12483
12484 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
12485 Fkill_emacs (Qnil, Qnil);
12486
12487 ensure_echo_area_buffers ();
12488
12489 if (!message_buf_print)
12490 {
12491
12492
12493 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12494 echo_area_buffer[0] = echo_buffer[1];
12495 else
12496 echo_area_buffer[0] = echo_buffer[0];
12497
12498
12499 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12500 bset_truncate_lines (current_buffer, Qnil);
12501
12502 if (Z > BEG)
12503 {
12504 specpdl_ref count = SPECPDL_INDEX ();
12505 specbind (Qinhibit_read_only, Qt);
12506
12507 del_range (BEG, Z);
12508 unbind_to (count, Qnil);
12509 }
12510 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
12511
12512
12513
12514
12515
12516
12517
12518 if (unibyte_display_via_language_environment
12519 && !multibyte_p
12520 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
12521 Fset_buffer_multibyte (Qnil);
12522 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
12523 Fset_buffer_multibyte (Qt);
12524
12525
12526 if (minibuffer_auto_raise)
12527 {
12528 struct frame *sf = SELECTED_FRAME ();
12529 Lisp_Object mini_window;
12530 mini_window = FRAME_MINIBUF_WINDOW (sf);
12531 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
12532 }
12533
12534 message_log_maybe_newline ();
12535 message_buf_print = true;
12536 }
12537 else
12538 {
12539 if (NILP (echo_area_buffer[0]))
12540 {
12541 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12542 echo_area_buffer[0] = echo_buffer[1];
12543 else
12544 echo_area_buffer[0] = echo_buffer[0];
12545 }
12546
12547 if (current_buffer != XBUFFER (echo_area_buffer[0]))
12548 {
12549
12550 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12551 bset_truncate_lines (current_buffer, Qnil);
12552 }
12553 }
12554 }
12555
12556
12557
12558
12559
12560
12561
12562 static bool
12563 display_echo_area (struct window *w)
12564 {
12565 bool no_message_p, window_height_changed_p;
12566
12567
12568
12569
12570
12571
12572 specpdl_ref count = inhibit_garbage_collection ();
12573
12574
12575
12576
12577
12578 bool i = display_last_displayed_message_p;
12579
12580
12581
12582 no_message_p = NILP (echo_area_buffer[i]);
12583
12584 window_height_changed_p
12585 = with_echo_area_buffer (w, display_last_displayed_message_p,
12586 display_echo_area_1, w, Qnil);
12587
12588 if (no_message_p)
12589 echo_area_buffer[i] = Qnil;
12590
12591 unbind_to (count, Qnil);
12592 return window_height_changed_p;
12593 }
12594
12595
12596
12597
12598
12599
12600
12601
12602 static bool
12603 display_echo_area_1 (void *a1, Lisp_Object a2)
12604 {
12605 struct window *w = a1;
12606 Lisp_Object window;
12607 struct text_pos start;
12608
12609
12610
12611
12612 forget_escape_and_glyphless_faces ();
12613
12614
12615
12616
12617 bool window_height_changed_p = resize_mini_window (w, false);
12618
12619
12620 SET_TEXT_POS_FROM_MARKER (start, w->start);
12621
12622
12623 clear_glyph_matrix (w->desired_matrix);
12624 XSETWINDOW (window, w);
12625 void *itdata = bidi_shelve_cache ();
12626 try_window (window, start, 0);
12627 bidi_unshelve_cache (itdata, false);
12628
12629 return window_height_changed_p;
12630 }
12631
12632
12633
12634
12635
12636
12637 void
12638 resize_echo_area_exactly (void)
12639 {
12640 if (BUFFERP (echo_area_buffer[0])
12641 && WINDOWP (echo_area_window))
12642 {
12643 struct window *w = XWINDOW (echo_area_window);
12644 Lisp_Object resize_exactly = (minibuf_level == 0 ? Qt : Qnil);
12645 bool resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
12646 w, resize_exactly);
12647 if (resized_p)
12648 {
12649 windows_or_buffers_changed = 42;
12650 update_mode_lines = 30;
12651 redisplay_internal ();
12652 }
12653 }
12654 }
12655
12656
12657
12658
12659
12660
12661
12662
12663 static bool
12664 resize_mini_window_1 (void *a1, Lisp_Object exactly)
12665 {
12666 return resize_mini_window (a1, !NILP (exactly));
12667 }
12668
12669
12670
12671
12672
12673
12674
12675
12676
12677
12678
12679
12680
12681 bool
12682 resize_mini_window (struct window *w, bool exact_p)
12683 {
12684 struct frame *f = XFRAME (w->frame);
12685 int old_height = WINDOW_BOX_TEXT_HEIGHT (w);
12686
12687 eassert (MINI_WINDOW_P (w));
12688
12689
12690
12691
12692
12693
12694
12695 if (!NILP (Vinhibit_redisplay))
12696 return false;
12697
12698
12699 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12700 set_marker_both (w->start, w->contents,
12701 BUF_BEGV (XBUFFER (w->contents)),
12702 BUF_BEGV_BYTE (XBUFFER (w->contents)));
12703
12704
12705 if ((NILP (Vresize_mini_windows)
12706 && (NILP (resize_mini_frames) || !FRAME_MINIBUF_ONLY_P (f)))
12707 || (FRAME_X_P (f) && FRAME_OUTPUT_DATA (f) == NULL))
12708 return false;
12709
12710 if (FRAME_MINIBUF_ONLY_P (f))
12711 {
12712 if (!NILP (resize_mini_frames))
12713 safe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
12714 }
12715 else
12716 {
12717 struct it it;
12718 int unit = FRAME_LINE_HEIGHT (f);
12719 int height, max_height;
12720 struct text_pos start;
12721 struct buffer *old_current_buffer = NULL;
12722 int windows_height = FRAME_INNER_HEIGHT (f);
12723
12724 if (current_buffer != XBUFFER (w->contents))
12725 {
12726 old_current_buffer = current_buffer;
12727 set_buffer_internal (XBUFFER (w->contents));
12728 }
12729
12730 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
12731
12732
12733 if (FLOATP (Vmax_mini_window_height))
12734 max_height = XFLOAT_DATA (Vmax_mini_window_height) * windows_height;
12735 else if (FIXNUMP (Vmax_mini_window_height))
12736 max_height = XFIXNUM (Vmax_mini_window_height) * unit;
12737 else
12738 max_height = windows_height / 4;
12739
12740
12741 max_height = clip_to_bounds (unit, max_height, windows_height);
12742
12743
12744 last_height = 0;
12745 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
12746
12747
12748 if (it.max_ascent == 0 && it.max_descent == 0)
12749 {
12750 height = it.current_y;
12751
12752
12753
12754
12755
12756 if (!(it.line_wrap == TRUNCATE
12757 && it.current_x <= it.first_visible_x
12758 && ZV_BYTE > 1
12759 && FETCH_BYTE (ZV_BYTE - 1) != '\n'))
12760 height += last_height;
12761 }
12762 else
12763 height = it.current_y + it.max_ascent + it.max_descent;
12764 height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
12765
12766
12767 if (height > max_height)
12768 {
12769 height = (max_height / unit) * unit;
12770 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12771 {
12772 init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
12773 move_it_vertically_backward (&it, height - unit);
12774
12775
12776
12777
12778
12779
12780
12781
12782
12783 move_it_by_lines (&it, 0);
12784 start = it.current.pos;
12785
12786
12787 w->start_at_line_beg = false;
12788 SET_MARKER_FROM_TEXT_POS (w->start, start);
12789 }
12790 }
12791 else
12792 {
12793 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
12794 SET_MARKER_FROM_TEXT_POS (w->start, start);
12795 }
12796
12797 if (EQ (Vresize_mini_windows, Qgrow_only))
12798 {
12799
12800
12801 if (height > old_height)
12802 grow_mini_window (w, height - old_height);
12803 else if (height < old_height && (exact_p || BEGV == ZV))
12804 shrink_mini_window (w);
12805 }
12806 else if (height != old_height)
12807
12808 grow_mini_window (w, height - old_height);
12809
12810 if (old_current_buffer)
12811 set_buffer_internal (old_current_buffer);
12812 }
12813
12814 return WINDOW_BOX_TEXT_HEIGHT (w) != old_height;
12815 }
12816
12817
12818
12819
12820
12821 Lisp_Object
12822 current_message (void)
12823 {
12824 Lisp_Object msg;
12825
12826 if (!BUFFERP (echo_area_buffer[0]))
12827 msg = Qnil;
12828 else
12829 {
12830 with_echo_area_buffer (0, 0, current_message_1, &msg, Qnil);
12831 if (NILP (msg))
12832 echo_area_buffer[0] = Qnil;
12833 }
12834
12835 return msg;
12836 }
12837
12838
12839 static bool
12840 current_message_1 (void *a1, Lisp_Object a2)
12841 {
12842 Lisp_Object *msg = a1;
12843
12844 if (Z > BEG)
12845 *msg = make_buffer_string (BEG, Z, true);
12846 else
12847 *msg = Qnil;
12848 return false;
12849 }
12850
12851
12852
12853
12854
12855
12856
12857 bool
12858 push_message (void)
12859 {
12860 Lisp_Object msg = current_message ();
12861 Vmessage_stack = Fcons (msg, Vmessage_stack);
12862 return STRINGP (msg);
12863 }
12864
12865
12866
12867
12868 void
12869 restore_message (void)
12870 {
12871 eassert (CONSP (Vmessage_stack));
12872 message3_nolog (XCAR (Vmessage_stack));
12873 }
12874
12875
12876
12877
12878 void
12879 pop_message_unwind (void)
12880 {
12881
12882 eassert (CONSP (Vmessage_stack));
12883 Vmessage_stack = XCDR (Vmessage_stack);
12884 }
12885
12886
12887
12888
12889
12890
12891 void
12892 check_message_stack (void)
12893 {
12894 if (!NILP (Vmessage_stack))
12895 emacs_abort ();
12896 }
12897
12898 void
12899 clear_message_stack (void)
12900 {
12901 Vmessage_stack = Qnil;
12902 }
12903
12904
12905
12906
12907 void
12908 truncate_echo_area (ptrdiff_t nchars)
12909 {
12910 if (nchars == 0)
12911 echo_area_buffer[0] = Qnil;
12912 else if (!noninteractive
12913 && INTERACTIVE
12914 && !NILP (echo_area_buffer[0]))
12915 {
12916 struct frame *sf = SELECTED_FRAME ();
12917
12918
12919
12920 if (sf->glyphs_initialized_p)
12921 with_echo_area_buffer (0, 0, truncate_message_1,
12922 (void *) (intptr_t) nchars, Qnil);
12923 }
12924 }
12925
12926
12927
12928
12929
12930 static bool
12931 truncate_message_1 (void *a1, Lisp_Object a2)
12932 {
12933 intptr_t nchars = (intptr_t) a1;
12934 if (BEG + nchars < Z)
12935 del_range (BEG + nchars, Z);
12936 if (Z == BEG)
12937 echo_area_buffer[0] = Qnil;
12938 return false;
12939 }
12940
12941 extern intptr_t garbage_collection_inhibited;
12942
12943
12944
12945 static void
12946 set_message (Lisp_Object string)
12947 {
12948 Lisp_Object message = Qnil;
12949
12950 eassert (STRINGP (string));
12951
12952 if (FUNCTIONP (Vset_message_function)
12953
12954
12955
12956 && !garbage_collection_inhibited)
12957 {
12958 specpdl_ref count = SPECPDL_INDEX ();
12959 specbind (Qinhibit_quit, Qt);
12960 message = safe_call1 (Vset_message_function, string);
12961 unbind_to (count, Qnil);
12962
12963 if (STRINGP (message))
12964 {
12965 string = message;
12966 message = Qnil;
12967 }
12968 }
12969
12970 if (NILP (message))
12971 {
12972 message_enable_multibyte = STRING_MULTIBYTE (string);
12973
12974 with_echo_area_buffer (0, -1, set_message_1, 0, string);
12975 message_buf_print = false;
12976 help_echo_showing_p = false;
12977 }
12978
12979 if (STRINGP (Vdebug_on_message)
12980 && STRINGP (string)
12981 && fast_string_match (Vdebug_on_message, string) >= 0)
12982 call_debugger (list2 (Qerror, string));
12983 }
12984
12985
12986
12987
12988
12989
12990 static bool
12991 set_message_1 (void *a1, Lisp_Object string)
12992 {
12993 eassert (STRINGP (string));
12994
12995
12996
12997
12998
12999
13000 if (!message_enable_multibyte
13001 && unibyte_display_via_language_environment
13002 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
13003 Fset_buffer_multibyte (Qnil);
13004 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
13005 Fset_buffer_multibyte (Qt);
13006
13007 bset_truncate_lines (current_buffer, message_truncate_lines ? Qt : Qnil);
13008 if (!NILP (BVAR (current_buffer, bidi_display_reordering)))
13009 bset_bidi_paragraph_direction (current_buffer, Qleft_to_right);
13010
13011
13012 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
13013
13014
13015
13016
13017 insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), true);
13018
13019 return false;
13020 }
13021
13022
13023
13024
13025
13026 void
13027 clear_message (bool current_p, bool last_displayed_p)
13028 {
13029 Lisp_Object preserve = Qnil;
13030
13031 if (current_p)
13032 {
13033 if (FUNCTIONP (Vclear_message_function)
13034
13035 && !garbage_collection_inhibited)
13036 {
13037 specpdl_ref count = SPECPDL_INDEX ();
13038 specbind (Qinhibit_quit, Qt);
13039 preserve = safe_call (1, Vclear_message_function);
13040 unbind_to (count, Qnil);
13041 }
13042
13043 if (!EQ (preserve, Qdont_clear_message))
13044 {
13045 echo_area_buffer[0] = Qnil;
13046 message_cleared_p = true;
13047 }
13048 }
13049
13050 if (last_displayed_p)
13051 echo_area_buffer[1] = Qnil;
13052
13053 message_buf_print = false;
13054 }
13055
13056
13057
13058
13059
13060
13061
13062
13063
13064
13065 static void
13066 clear_garbaged_frames (void)
13067 {
13068 if (frame_garbaged)
13069 {
13070 Lisp_Object tail, frame;
13071 struct frame *sf = SELECTED_FRAME ();
13072
13073 FOR_EACH_FRAME (tail, frame)
13074 {
13075 struct frame *f = XFRAME (frame);
13076
13077 if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
13078 {
13079 if (f->resized_p
13080
13081
13082
13083
13084
13085 && !(f != sf && (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))))
13086 redraw_frame (f);
13087 else
13088 clear_current_matrices (f);
13089
13090 #ifdef HAVE_WINDOW_SYSTEM
13091 if (FRAME_WINDOW_P (f)
13092 && FRAME_RIF (f)->clear_under_internal_border)
13093 FRAME_RIF (f)->clear_under_internal_border (f);
13094 #endif
13095 fset_redisplay (f);
13096 f->garbaged = false;
13097 f->resized_p = false;
13098 }
13099 }
13100
13101 frame_garbaged = false;
13102 }
13103 }
13104
13105
13106
13107
13108
13109 static void
13110 echo_area_display (bool update_frame_p)
13111 {
13112 Lisp_Object mini_window;
13113 struct window *w;
13114 struct frame *f;
13115 bool window_height_changed_p = false;
13116 struct frame *sf = SELECTED_FRAME ();
13117
13118 mini_window = FRAME_MINIBUF_WINDOW (sf);
13119 if (NILP (mini_window))
13120 return;
13121
13122 w = XWINDOW (mini_window);
13123 f = XFRAME (WINDOW_FRAME (w));
13124
13125
13126 if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
13127 return;
13128
13129 #ifdef HAVE_WINDOW_SYSTEM
13130
13131
13132
13133 if (FRAME_INITIAL_P (XFRAME (selected_frame)))
13134 return;
13135 #endif
13136
13137
13138 clear_garbaged_frames ();
13139
13140 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
13141 {
13142 echo_area_window = mini_window;
13143 window_height_changed_p = display_echo_area (w);
13144 w->must_be_updated_p = true;
13145
13146
13147
13148
13149
13150 if (update_frame_p && !redisplaying_p)
13151 {
13152 int n = 0;
13153
13154
13155
13156
13157
13158
13159 if (!display_completed)
13160 {
13161 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), false);
13162
13163 #ifdef HAVE_WINDOW_SYSTEM
13164 if (FRAME_WINDOW_P (f)
13165 && FRAME_RIF (f)->clear_under_internal_border)
13166 FRAME_RIF (f)->clear_under_internal_border (f);
13167 #endif
13168 }
13169
13170 if (window_height_changed_p
13171
13172
13173 && !NILP (Vrun_hooks))
13174 {
13175
13176
13177
13178 specpdl_ref count = SPECPDL_INDEX ();
13179 specbind (Qredisplay_dont_pause, Qt);
13180 fset_redisplay (f);
13181 redisplay_internal ();
13182 unbind_to (count, Qnil);
13183 }
13184 else if (FRAME_WINDOW_P (f) && n == 0)
13185 {
13186
13187
13188
13189 update_single_window (w);
13190 flush_frame (f);
13191 }
13192 else
13193 update_frame (f, true, true);
13194
13195
13196
13197
13198 if (cursor_in_echo_area)
13199 wset_redisplay (XWINDOW (mini_window));
13200 }
13201 }
13202 else if (!EQ (mini_window, selected_window))
13203 wset_redisplay (XWINDOW (mini_window));
13204
13205
13206 echo_area_buffer[1] = echo_area_buffer[0];
13207
13208 echo_message_buffer = Qnil;
13209
13210
13211
13212
13213 if (EQ (mini_window, selected_window))
13214 CHARPOS (this_line_start_pos) = 0;
13215
13216 if (window_height_changed_p)
13217 {
13218 fset_redisplay (f);
13219
13220
13221
13222
13223
13224 clear_garbaged_frames ();
13225 }
13226 }
13227
13228
13229
13230 static bool
13231 window_buffer_changed (struct window *w)
13232 {
13233 struct buffer *b = XBUFFER (w->contents);
13234
13235 eassert (BUFFER_LIVE_P (b));
13236
13237 return (BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star;
13238 }
13239
13240
13241
13242 static bool
13243 mode_line_update_needed (struct window *w)
13244 {
13245 return (w->column_number_displayed != -1
13246 && !(PT == w->last_point && !window_outdated (w))
13247 && (w->column_number_displayed != current_column ()));
13248 }
13249
13250
13251
13252
13253 static bool
13254 window_frozen_p (struct window *w)
13255 {
13256 if (FRAME_WINDOWS_FROZEN (XFRAME (WINDOW_FRAME (w))))
13257 {
13258 Lisp_Object window;
13259
13260 XSETWINDOW (window, w);
13261 if (MINI_WINDOW_P (w))
13262 return false;
13263 else if (EQ (window, selected_window))
13264 return false;
13265 else if (MINI_WINDOW_P (XWINDOW (selected_window))
13266 && EQ (window, Vminibuf_scroll_window))
13267
13268 return false;
13269 else
13270 return true;
13271 }
13272 return false;
13273 }
13274
13275
13276
13277
13278
13279
13280
13281
13282
13283 static char *mode_line_noprop_buf;
13284
13285
13286
13287 static char *mode_line_noprop_buf_end;
13288 static char *mode_line_noprop_ptr;
13289
13290 #define MODE_LINE_NOPROP_LEN(start) \
13291 ((mode_line_noprop_ptr - mode_line_noprop_buf) - start)
13292
13293 static enum {
13294 MODE_LINE_DISPLAY = 0,
13295 MODE_LINE_TITLE,
13296 MODE_LINE_NOPROP,
13297 MODE_LINE_STRING
13298 } mode_line_target;
13299
13300
13301
13302 static Lisp_Object mode_line_proptrans_alist;
13303
13304
13305 static Lisp_Object mode_line_string_list;
13306
13307
13308 static Lisp_Object mode_line_string_face;
13309 static Lisp_Object mode_line_string_face_prop;
13310
13311
13312
13313
13314 static Lisp_Object Vmode_line_unwind_vector;
13315
13316 static Lisp_Object
13317 format_mode_line_unwind_data (struct frame *target_frame,
13318 struct buffer *obuf,
13319 Lisp_Object owin,
13320 bool save_proptrans)
13321 {
13322 Lisp_Object vector, tmp;
13323
13324
13325
13326 vector = Vmode_line_unwind_vector;
13327 Vmode_line_unwind_vector = Qnil;
13328
13329 if (NILP (vector))
13330 vector = make_nil_vector (12);
13331
13332 ASET (vector, 0, make_fixnum (mode_line_target));
13333 ASET (vector, 1, make_fixnum (MODE_LINE_NOPROP_LEN (0)));
13334 ASET (vector, 2, mode_line_string_list);
13335 ASET (vector, 3, save_proptrans ? mode_line_proptrans_alist : Qt);
13336 ASET (vector, 4, mode_line_string_face);
13337 ASET (vector, 5, mode_line_string_face_prop);
13338
13339 if (obuf)
13340 XSETBUFFER (tmp, obuf);
13341 else
13342 tmp = Qnil;
13343 ASET (vector, 6, tmp);
13344 ASET (vector, 7, owin);
13345 if (target_frame)
13346 {
13347 Lisp_Object buffer = XWINDOW (target_frame->selected_window)->contents;
13348 struct buffer *b = XBUFFER (buffer);
13349 struct buffer *cb = current_buffer;
13350
13351
13352
13353
13354 ASET (vector, 8, target_frame->selected_window);
13355 if (FRAME_TERMCAP_P (target_frame))
13356 ASET (vector, 9, FRAME_TTY (target_frame)->top_frame);
13357
13358
13359
13360
13361 ASET (vector, 10, buffer);
13362 current_buffer = b;
13363 ASET (vector, 11, build_marker (current_buffer, PT, PT_BYTE));
13364 current_buffer = cb;
13365 }
13366
13367 return vector;
13368 }
13369
13370 static void
13371 unwind_format_mode_line (Lisp_Object vector)
13372 {
13373 Lisp_Object old_window = AREF (vector, 7);
13374 Lisp_Object target_frame_window = AREF (vector, 8);
13375 Lisp_Object old_top_frame = AREF (vector, 9);
13376
13377 mode_line_target = XFIXNUM (AREF (vector, 0));
13378 mode_line_noprop_ptr = mode_line_noprop_buf + XFIXNUM (AREF (vector, 1));
13379 mode_line_string_list = AREF (vector, 2);
13380 if (! EQ (AREF (vector, 3), Qt))
13381 mode_line_proptrans_alist = AREF (vector, 3);
13382 mode_line_string_face = AREF (vector, 4);
13383 mode_line_string_face_prop = AREF (vector, 5);
13384
13385
13386 if (WINDOW_LIVE_P (old_window))
13387 {
13388
13389
13390
13391 if (WINDOW_LIVE_P (target_frame_window))
13392 {
13393 Lisp_Object frame
13394 = WINDOW_FRAME (XWINDOW (target_frame_window));
13395
13396 if (!EQ (frame, WINDOW_FRAME (XWINDOW (old_window))))
13397 Fselect_window (target_frame_window, Qt);
13398
13399 if (!NILP (old_top_frame) && !EQ (old_top_frame, frame)
13400
13401
13402 && FRAME_LIVE_P (XFRAME (old_top_frame)))
13403 Fselect_frame (old_top_frame, Qt);
13404 }
13405
13406 Fselect_window (old_window, Qt);
13407
13408
13409
13410
13411 if (WINDOW_LIVE_P (target_frame_window))
13412 {
13413 Lisp_Object buffer = AREF (vector, 10);
13414
13415 if (BUFFER_LIVE_P (XBUFFER (buffer)))
13416 {
13417 struct buffer *cb = current_buffer;
13418
13419 current_buffer = XBUFFER (buffer);
13420 set_point_from_marker (AREF (vector, 11));
13421 ASET (vector, 11, Qnil);
13422 current_buffer = cb;
13423 }
13424 }
13425 }
13426
13427 if (!NILP (AREF (vector, 6)))
13428 {
13429 set_buffer_internal_1 (XBUFFER (AREF (vector, 6)));
13430 ASET (vector, 6, Qnil);
13431 }
13432
13433 Vmode_line_unwind_vector = vector;
13434 }
13435
13436
13437
13438
13439
13440 static void
13441 store_mode_line_noprop_char (char c)
13442 {
13443
13444
13445 if (mode_line_noprop_ptr == mode_line_noprop_buf_end)
13446 {
13447 ptrdiff_t len = MODE_LINE_NOPROP_LEN (0);
13448 ptrdiff_t size = len;
13449 mode_line_noprop_buf =
13450 xpalloc (mode_line_noprop_buf, &size, 1, STRING_BYTES_BOUND, 1);
13451 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
13452 mode_line_noprop_ptr = mode_line_noprop_buf + len;
13453 }
13454
13455 *mode_line_noprop_ptr++ = c;
13456 }
13457
13458
13459
13460
13461
13462
13463
13464
13465
13466
13467 static int
13468 store_mode_line_noprop (const char *string, int field_width, int precision)
13469 {
13470 const unsigned char *str = (const unsigned char *) string;
13471 int n = 0;
13472 ptrdiff_t dummy, nbytes;
13473
13474
13475 nbytes = strlen (string);
13476 n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
13477 while (nbytes--)
13478 store_mode_line_noprop_char (*str++);
13479
13480
13481 while (field_width > 0
13482 && n < field_width)
13483 {
13484 store_mode_line_noprop_char (' ');
13485 ++n;
13486 }
13487
13488 return n;
13489 }
13490
13491
13492
13493
13494
13495 #ifdef HAVE_WINDOW_SYSTEM
13496
13497
13498
13499
13500
13501 void
13502 gui_consider_frame_title (Lisp_Object frame)
13503 {
13504 struct frame *f = XFRAME (frame);
13505 Lisp_Object format_data;
13506
13507 if ((FRAME_WINDOW_P (f)
13508 || FRAME_MINIBUF_ONLY_P (f)
13509 || f->explicit_name)
13510 && !FRAME_TOOLTIP_P (f))
13511 {
13512
13513 Lisp_Object tail, other_frame, fmt;
13514 ptrdiff_t title_start;
13515 char *title;
13516 ptrdiff_t len;
13517 struct it it;
13518 specpdl_ref count = SPECPDL_INDEX ();
13519
13520 FOR_EACH_FRAME (tail, other_frame)
13521 {
13522 struct frame *tf = XFRAME (other_frame);
13523
13524 if (tf != f
13525 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
13526 && !FRAME_MINIBUF_ONLY_P (tf)
13527 && !FRAME_PARENT_FRAME (tf)
13528 && !FRAME_TOOLTIP_P (tf)
13529 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
13530 break;
13531 }
13532
13533
13534 multiple_frames = CONSP (tail);
13535
13536
13537
13538
13539
13540
13541
13542
13543
13544
13545
13546
13547 specbind (Qinhibit_redisplay, Qt);
13548
13549
13550
13551
13552
13553
13554
13555
13556 format_data = format_mode_line_unwind_data (f, current_buffer,
13557 selected_window,
13558 false);
13559 record_unwind_protect (unwind_format_mode_line, format_data);
13560
13561 Fselect_window (f->selected_window, Qt);
13562 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->contents));
13563 fmt = (FRAME_ICONIFIED_P (f) && !EQ (Vicon_title_format, Qt)
13564 ? Vicon_title_format : Vframe_title_format);
13565
13566 mode_line_target = MODE_LINE_TITLE;
13567 title_start = MODE_LINE_NOPROP_LEN (0);
13568 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
13569 NULL, DEFAULT_FACE_ID);
13570 display_mode_element (&it, 0, -1, -1, fmt, Qnil, false);
13571 len = MODE_LINE_NOPROP_LEN (title_start);
13572 title = mode_line_noprop_buf + title_start;
13573
13574
13575 ptrdiff_t nchars = 0;
13576 len = str_as_multibyte ((unsigned char *) title,
13577 mode_line_noprop_buf_end - title,
13578 len, &nchars);
13579 unbind_to (count, Qnil);
13580
13581
13582
13583
13584
13585
13586 if ((! STRINGP (f->name)
13587 || SBYTES (f->name) != len
13588 || memcmp (title, SDATA (f->name), len) != 0)
13589 && FRAME_TERMINAL (f)->implicit_set_name_hook)
13590 {
13591 Lisp_Object title_string = make_multibyte_string (title, nchars, len);
13592 FRAME_TERMINAL (f)->implicit_set_name_hook (f, title_string, Qnil);
13593 }
13594 }
13595 }
13596
13597 #endif
13598
13599
13600
13601
13602
13603
13604
13605 #define REDISPLAY_SOME_P() \
13606 ((windows_or_buffers_changed == 0 \
13607 || windows_or_buffers_changed == REDISPLAY_SOME) \
13608 && (update_mode_lines == 0 \
13609 || update_mode_lines == REDISPLAY_SOME))
13610
13611 static bool
13612 needs_no_redisplay (struct window *w)
13613 {
13614 struct buffer *buffer = XBUFFER (w->contents);
13615 struct frame *f = XFRAME (w->frame);
13616 return (REDISPLAY_SOME_P ()
13617 && !w->redisplay
13618 && !w->update_mode_line
13619 && !f->face_change
13620 && !f->redisplay
13621 && !buffer->text->redisplay
13622 && window_point (w) == w->last_point);
13623 }
13624
13625
13626
13627
13628 static void
13629 prepare_menu_bars (void)
13630 {
13631 bool all_windows = windows_or_buffers_changed || update_mode_lines;
13632 bool some_windows = REDISPLAY_SOME_P ();
13633
13634 if (FUNCTIONP (Vpre_redisplay_function))
13635 {
13636 Lisp_Object windows = all_windows ? Qt : Qnil;
13637 if (all_windows && some_windows)
13638 {
13639 Lisp_Object ws = window_list ();
13640 for (windows = Qnil; CONSP (ws); ws = XCDR (ws))
13641 {
13642 Lisp_Object this = XCAR (ws);
13643 struct window *w = XWINDOW (this);
13644
13645
13646 if (!needs_no_redisplay (w))
13647 windows = Fcons (this, windows);
13648 }
13649 }
13650 safe__call1 (true, Vpre_redisplay_function, windows);
13651 }
13652
13653
13654
13655
13656 #ifdef HAVE_WINDOW_SYSTEM
13657 if (all_windows)
13658 {
13659 Lisp_Object tail, frame;
13660
13661 FOR_EACH_FRAME (tail, frame)
13662 {
13663 struct frame *f = XFRAME (frame);
13664 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13665 if (some_windows
13666 && !f->redisplay
13667 && !w->redisplay
13668 && !XBUFFER (w->contents)->text->redisplay)
13669 continue;
13670
13671 if (!FRAME_TOOLTIP_P (f)
13672 && (FRAME_ICONIFIED_P (f)
13673 || FRAME_VISIBLE_P (f) == 1
13674
13675
13676
13677
13678
13679
13680
13681
13682
13683 || (FRAME_VISIBLE_P (f) == 2 && FRAME_WINDOW_P (f))))
13684 gui_consider_frame_title (frame);
13685 }
13686 }
13687 #endif
13688
13689
13690
13691
13692 if (all_windows)
13693 {
13694 Lisp_Object tail, frame;
13695 specpdl_ref count = SPECPDL_INDEX ();
13696
13697
13698 bool menu_bar_hooks_run = false;
13699
13700 record_unwind_save_match_data ();
13701
13702 FOR_EACH_FRAME (tail, frame)
13703 {
13704 struct frame *f = XFRAME (frame);
13705 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13706
13707
13708 if (FRAME_TOOLTIP_P (f))
13709 continue;
13710
13711 if (some_windows
13712 && !f->redisplay
13713 && !w->redisplay
13714 && !XBUFFER (w->contents)->text->redisplay)
13715 continue;
13716
13717 if (!FRAME_PARENT_FRAME (f))
13718 menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
13719
13720 update_tab_bar (f, false);
13721 #ifdef HAVE_WINDOW_SYSTEM
13722 update_tool_bar (f, false);
13723 #endif
13724 }
13725
13726 unbind_to (count, Qnil);
13727 }
13728 else
13729 {
13730 struct frame *sf = SELECTED_FRAME ();
13731
13732 if (!FRAME_PARENT_FRAME (sf))
13733 update_menu_bar (sf, true, false);
13734
13735 update_tab_bar (sf, true);
13736 #ifdef HAVE_WINDOW_SYSTEM
13737 update_tool_bar (sf, true);
13738 #endif
13739 }
13740 }
13741
13742
13743
13744
13745
13746
13747
13748
13749
13750
13751
13752
13753
13754 static bool
13755 update_menu_bar (struct frame *f, bool save_match_data, bool hooks_run)
13756 {
13757 Lisp_Object window;
13758 struct window *w;
13759
13760
13761
13762
13763 if (inhibit_menubar_update)
13764 return hooks_run;
13765
13766 window = FRAME_SELECTED_WINDOW (f);
13767 w = XWINDOW (window);
13768
13769 if (FRAME_WINDOW_P (f)
13770 ?
13771 #ifdef HAVE_EXT_MENU_BAR
13772 FRAME_EXTERNAL_MENU_BAR (f)
13773 #else
13774 FRAME_MENU_BAR_LINES (f) > 0
13775 #endif
13776 : FRAME_MENU_BAR_LINES (f) > 0)
13777 {
13778
13779
13780
13781
13782
13783
13784
13785 if (windows_or_buffers_changed
13786
13787
13788 || update_mode_lines
13789 || window_buffer_changed (w))
13790 {
13791 struct buffer *prev = current_buffer;
13792 specpdl_ref count = SPECPDL_INDEX ();
13793
13794 specbind (Qinhibit_menubar_update, Qt);
13795
13796 set_buffer_internal_1 (XBUFFER (w->contents));
13797 if (save_match_data)
13798 record_unwind_save_match_data ();
13799 if (NILP (Voverriding_local_map_menu_flag))
13800 {
13801 specbind (Qoverriding_terminal_local_map, Qnil);
13802 specbind (Qoverriding_local_map, Qnil);
13803 }
13804
13805 if (!hooks_run)
13806 {
13807
13808 safe_run_hooks (Qactivate_menubar_hook);
13809
13810
13811
13812 safe_run_hooks (Qmenu_bar_update_hook);
13813
13814 hooks_run = true;
13815 }
13816
13817 XSETFRAME (Vmenu_updating_frame, f);
13818 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
13819
13820
13821 #ifdef HAVE_EXT_MENU_BAR
13822 if (FRAME_WINDOW_P (f))
13823 {
13824 #if defined (HAVE_NS)
13825
13826
13827 if (f == SELECTED_FRAME ())
13828 #endif
13829 set_frame_menubar (f, false);
13830 }
13831 else
13832
13833
13834 w->update_mode_line = true;
13835 #else
13836
13837
13838 w->update_mode_line = true;
13839 #endif
13840
13841 unbind_to (count, Qnil);
13842 set_buffer_internal_1 (prev);
13843 }
13844 }
13845
13846 return hooks_run;
13847 }
13848
13849
13850
13851
13852
13853
13854
13855
13856
13857
13858
13859
13860 static void
13861 restore_selected_window (Lisp_Object window)
13862 {
13863 if (WINDOW_LIVE_P (window))
13864
13865
13866 {
13867 selected_window = window;
13868 selected_frame = XWINDOW (window)->frame;
13869 FRAME_SELECTED_WINDOW (XFRAME (selected_frame)) = window;
13870 }
13871 else if (FRAMEP (selected_frame) && FRAME_LIVE_P (XFRAME (selected_frame)))
13872
13873
13874 selected_window = FRAME_SELECTED_WINDOW (XFRAME (selected_frame));
13875 else
13876
13877
13878
13879 {
13880 Lisp_Object tail;
13881 Lisp_Object frame UNINIT;
13882
13883 FOR_EACH_FRAME (tail, frame)
13884 {
13885 struct frame *f = XFRAME (frame);
13886
13887 if (!FRAME_PARENT_FRAME (f) && !FRAME_TOOLTIP_P (f))
13888 {
13889 selected_frame = frame;
13890 selected_window = FRAME_SELECTED_WINDOW (f);
13891
13892 return;
13893 }
13894 }
13895
13896
13897 emacs_abort ();
13898 }
13899 }
13900
13901
13902 static void
13903 restore_frame_selected_window (Lisp_Object window)
13904 {
13905 if (WINDOW_LIVE_P (window))
13906
13907
13908
13909 {
13910 Lisp_Object frame = XWINDOW (window)->frame;
13911
13912 FRAME_SELECTED_WINDOW (XFRAME (frame)) = window;
13913 if (EQ (frame, selected_frame))
13914 selected_window = window;
13915 }
13916 }
13917
13918
13919
13920
13921
13922
13923 static void
13924 update_tab_bar (struct frame *f, bool save_match_data)
13925 {
13926 bool do_update = false;
13927
13928 #ifdef HAVE_WINDOW_SYSTEM
13929 if (FRAME_WINDOW_P (f) && WINDOWP (f->tab_bar_window)) {
13930 if (WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0)
13931 do_update = true;
13932 }
13933 else
13934 #endif
13935 if (FRAME_TAB_BAR_LINES (f) > 0)
13936 do_update = true;
13937
13938 if (do_update)
13939 {
13940 Lisp_Object window;
13941 struct window *w;
13942
13943 window = FRAME_SELECTED_WINDOW (f);
13944 w = XWINDOW (window);
13945
13946
13947
13948
13949
13950
13951
13952
13953 if (windows_or_buffers_changed
13954 || w->update_mode_line
13955 || update_mode_lines
13956 || window_buffer_changed (w))
13957 {
13958 struct buffer *prev = current_buffer;
13959 specpdl_ref count = SPECPDL_INDEX ();
13960 Lisp_Object new_tab_bar;
13961 int new_n_tab_bar;
13962
13963
13964
13965
13966 set_buffer_internal_1 (XBUFFER (w->contents));
13967
13968
13969 if (save_match_data)
13970 record_unwind_save_match_data ();
13971
13972
13973 if (NILP (Voverriding_local_map_menu_flag))
13974 {
13975 specbind (Qoverriding_terminal_local_map, Qnil);
13976 specbind (Qoverriding_local_map, Qnil);
13977 }
13978
13979
13980
13981
13982
13983 eassert (EQ (selected_window,
13984
13985
13986 XFRAME (selected_frame)->selected_window));
13987 #ifdef HAVE_WINDOW_SYSTEM
13988 Lisp_Object frame;
13989 record_unwind_protect (restore_selected_window, selected_window);
13990 XSETFRAME (frame, f);
13991 selected_frame = frame;
13992 selected_window = FRAME_SELECTED_WINDOW (f);
13993 #endif
13994
13995
13996 new_tab_bar
13997 = tab_bar_items (Fcopy_sequence (f->tab_bar_items),
13998 &new_n_tab_bar);
13999
14000
14001 if (new_n_tab_bar != f->n_tab_bar_items
14002 || NILP (Fequal (new_tab_bar, f->tab_bar_items)))
14003 {
14004
14005
14006
14007 block_input ();
14008 fset_tab_bar_items (f, new_tab_bar);
14009 f->n_tab_bar_items = new_n_tab_bar;
14010 w->update_mode_line = true;
14011 unblock_input ();
14012 }
14013
14014 unbind_to (count, Qnil);
14015 set_buffer_internal_1 (prev);
14016 }
14017 }
14018 }
14019
14020
14021
14022
14023
14024
14025
14026
14027
14028
14029
14030 static void
14031 display_tab_bar (struct window *w)
14032 {
14033 struct frame *f = XFRAME (WINDOW_FRAME (w));
14034 struct it it;
14035 Lisp_Object items;
14036 int i;
14037
14038
14039 #ifdef HAVE_NTGUI
14040 if (FRAME_W32_P (f))
14041 return;
14042 #endif
14043 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14044 if (FRAME_X_P (f))
14045 return;
14046 #endif
14047
14048 #ifdef HAVE_NS
14049 if (FRAME_NS_P (f))
14050 return;
14051 #endif
14052
14053 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14054 eassert (!FRAME_WINDOW_P (f));
14055 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14056 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14057 TAB_BAR_FACE_ID);
14058 it.first_visible_x = 0;
14059 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14060 #elif defined (HAVE_X_WINDOWS)
14061 if (FRAME_WINDOW_P (f))
14062 {
14063
14064
14065 struct window *tab_w;
14066 tab_w = XWINDOW (f->tab_bar_window);
14067 init_iterator (&it, tab_w, -1, -1, tab_w->desired_matrix->rows,
14068 TAB_BAR_FACE_ID);
14069 it.first_visible_x = 0;
14070 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14071 }
14072 else
14073 #endif
14074 {
14075
14076
14077 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14078 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14079 TAB_BAR_FACE_ID);
14080 it.first_visible_x = 0;
14081 it.last_visible_x = FRAME_COLS (f);
14082 }
14083
14084
14085
14086
14087 it.paragraph_embedding = L2R;
14088
14089
14090 for (i = 0; i < FRAME_TAB_BAR_LINES (f); ++i)
14091 {
14092 struct glyph_row *row = it.glyph_row + i;
14093 clear_glyph_row (row);
14094 row->enabled_p = true;
14095 row->full_width_p = true;
14096 row->reversed_p = false;
14097 }
14098
14099
14100 items = it.f->tab_bar_items;
14101 int j;
14102 for (i = 0, j = 0; i < it.f->n_tab_bar_items; ++i, j += TAB_BAR_ITEM_NSLOTS)
14103 {
14104 Lisp_Object string = AREF (items, j + TAB_BAR_ITEM_CAPTION);
14105
14106
14107 if (NILP (string))
14108 break;
14109
14110 if (it.current_x < it.last_visible_x)
14111 display_string (NULL, string, Qnil, 0, 0, &it,
14112 SCHARS (string), 0, 0, STRING_MULTIBYTE (string));
14113 }
14114
14115
14116 if (it.current_x < it.last_visible_x)
14117 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
14118
14119
14120 compute_line_metrics (&it);
14121 }
14122
14123 #ifdef HAVE_WINDOW_SYSTEM
14124
14125
14126
14127
14128
14129 static void
14130 build_desired_tab_bar_string (struct frame *f)
14131 {
14132 int i;
14133 Lisp_Object caption;
14134
14135 caption = Qnil;
14136
14137
14138 fset_desired_tab_bar_string (f, build_string (""));
14139
14140
14141
14142
14143 for (i = 0; i < f->n_tab_bar_items; ++i)
14144 {
14145 #define PROP(IDX) \
14146 AREF (f->tab_bar_items, i * TAB_BAR_ITEM_NSLOTS + (IDX))
14147
14148 caption = Fcopy_sequence (PROP (TAB_BAR_ITEM_CAPTION));
14149
14150
14151
14152
14153
14154 AUTO_LIST2 (props, Qmenu_item, make_fixnum (i * TAB_BAR_ITEM_NSLOTS));
14155
14156 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14157 props, caption);
14158
14159 f->desired_tab_bar_string =
14160 concat2 (f->desired_tab_bar_string, caption);
14161
14162 #undef PROP
14163 }
14164 }
14165
14166
14167
14168
14169
14170
14171
14172
14173
14174
14175
14176
14177
14178
14179 static void
14180 display_tab_bar_line (struct it *it, int height)
14181 {
14182 struct glyph_row *row = it->glyph_row;
14183 int max_x = it->last_visible_x;
14184 struct glyph *last;
14185
14186
14187 clear_glyph_row (row);
14188 row->enabled_p = true;
14189 row->y = it->current_y;
14190
14191
14192
14193 it->start_of_box_run_p = true;
14194
14195 bool enough = false;
14196 while (it->current_x < max_x)
14197 {
14198 int x, n_glyphs_before, i, nglyphs;
14199 struct it it_before;
14200
14201
14202 if (!get_next_display_element (it))
14203 {
14204
14205 if (height < 0 && !it->hpos)
14206 return;
14207 break;
14208 }
14209
14210
14211 n_glyphs_before = row->used[TEXT_AREA];
14212 it_before = *it;
14213
14214 PRODUCE_GLYPHS (it);
14215
14216 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
14217 i = 0;
14218 x = it_before.current_x;
14219 while (i < nglyphs)
14220 {
14221 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
14222
14223 if (x + glyph->pixel_width > max_x)
14224 {
14225
14226 row->used[TEXT_AREA] = n_glyphs_before;
14227 *it = it_before;
14228
14229
14230
14231 if (n_glyphs_before == 0
14232 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
14233 break;
14234 goto out;
14235 }
14236
14237 ++it->hpos;
14238 x += glyph->pixel_width;
14239 ++i;
14240 }
14241
14242 enough = ITERATOR_AT_END_OF_LINE_P (it);
14243 set_iterator_to_next (it, true);
14244
14245
14246 if (enough)
14247 break;
14248 }
14249
14250 out:;
14251
14252 row->displays_text_p = row->used[TEXT_AREA] != 0;
14253
14254
14255
14256
14257
14258
14259
14260 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14261 && !EQ (Vauto_resize_tab_bars, Qgrow_only))
14262 it->face_id = DEFAULT_FACE_ID;
14263
14264 extend_face_to_end_of_line (it);
14265 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
14266 last->right_box_line_p = true;
14267 if (last == row->glyphs[TEXT_AREA])
14268 last->left_box_line_p = true;
14269
14270
14271 if ((height -= it->max_ascent + it->max_descent) > 0)
14272 {
14273
14274 height %= FRAME_LINE_HEIGHT (it->f);
14275 it->max_ascent += height / 2;
14276 it->max_descent += (height + 1) / 2;
14277 }
14278
14279 compute_line_metrics (it);
14280
14281
14282 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
14283 {
14284 row->height = row->phys_height = it->last_visible_y - row->y;
14285 row->visible_height = row->height;
14286 row->ascent = row->phys_ascent = 0;
14287 row->extra_line_spacing = 0;
14288 }
14289
14290 row->full_width_p = true;
14291 row->continued_p = false;
14292 row->truncated_on_left_p = false;
14293 row->truncated_on_right_p = false;
14294
14295 it->current_x = it->hpos = 0;
14296 it->current_y += row->height;
14297 ++it->vpos;
14298 ++it->glyph_row;
14299 }
14300
14301
14302
14303
14304
14305 static int
14306 tab_bar_height (struct frame *f, int *n_rows, bool pixelwise)
14307 {
14308 struct window *w = XWINDOW (f->tab_bar_window);
14309 struct it it;
14310
14311
14312
14313 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
14314
14315
14316
14317 init_iterator (&it, w, -1, -1, temp_row, TAB_BAR_FACE_ID);
14318 temp_row->reversed_p = false;
14319 it.first_visible_x = 0;
14320 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14321 reseat_to_string (&it, NULL, f->desired_tab_bar_string,
14322 0, 0, 0, STRING_MULTIBYTE (f->desired_tab_bar_string));
14323 it.paragraph_embedding = L2R;
14324
14325 clear_glyph_row (temp_row);
14326 while (!ITERATOR_AT_END_P (&it))
14327 {
14328 it.glyph_row = temp_row;
14329 display_tab_bar_line (&it, -1);
14330 }
14331 clear_glyph_row (temp_row);
14332
14333
14334 if (n_rows)
14335 *n_rows = it.vpos > 0 ? it.vpos : -1;
14336
14337 if (pixelwise)
14338 return it.current_y;
14339 else
14340 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
14341 }
14342
14343 DEFUN ("tab-bar-height", Ftab_bar_height, Stab_bar_height,
14344 0, 2, 0,
14345 doc:
14346
14347 )
14348 (Lisp_Object frame, Lisp_Object pixelwise)
14349 {
14350 int height = 0;
14351
14352 struct frame *f = decode_any_frame (frame);
14353
14354 if (WINDOWP (f->tab_bar_window)
14355 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tab_bar_window)) > 0)
14356 {
14357 update_tab_bar (f, true);
14358 if (f->n_tab_bar_items)
14359 {
14360 build_desired_tab_bar_string (f);
14361 height = tab_bar_height (f, NULL, !NILP (pixelwise));
14362 }
14363 }
14364
14365 return make_fixnum (height);
14366 }
14367
14368
14369
14370
14371 static bool
14372 redisplay_tab_bar (struct frame *f)
14373 {
14374 struct window *w;
14375 struct it it;
14376 struct glyph_row *row;
14377
14378 f->tab_bar_redisplayed = true;
14379
14380
14381
14382
14383
14384 if (!WINDOWP (f->tab_bar_window)
14385 || (w = XWINDOW (f->tab_bar_window),
14386 WINDOW_TOTAL_LINES (w) == 0))
14387 {
14388
14389
14390
14391
14392
14393 f->tab_bar_resized = true;
14394
14395 return false;
14396 }
14397
14398
14399 build_desired_tab_bar_string (f);
14400
14401 int new_nrows;
14402 int new_height = tab_bar_height (f, &new_nrows, true);
14403
14404 if (f->n_tab_bar_rows == 0)
14405 {
14406 f->n_tab_bar_rows = new_nrows;
14407 if (new_height != WINDOW_PIXEL_HEIGHT (w))
14408 frame_default_tab_bar_height = new_height;
14409 }
14410
14411
14412
14413 if (new_nrows > f->n_tab_bar_rows
14414 || (EQ (Vauto_resize_tab_bars, Qgrow_only)
14415 && !f->minimize_tab_bar_window_p
14416 && new_height > WINDOW_PIXEL_HEIGHT (w))
14417 || (! EQ (Vauto_resize_tab_bars, Qgrow_only)
14418 && new_height < WINDOW_PIXEL_HEIGHT (w)))
14419 {
14420 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14421 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14422 if (new_nrows != f->n_tab_bar_rows)
14423 f->n_tab_bar_rows = new_nrows;
14424 clear_glyph_matrix (w->desired_matrix);
14425 f->fonts_changed = true;
14426 return true;
14427 }
14428
14429
14430 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TAB_BAR_FACE_ID);
14431 it.first_visible_x = 0;
14432 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14433 row = it.glyph_row;
14434 row->reversed_p = false;
14435 reseat_to_string (&it, NULL, f->desired_tab_bar_string, 0, 0, 0,
14436 STRING_MULTIBYTE (f->desired_tab_bar_string));
14437
14438
14439
14440
14441
14442
14443
14444 it.paragraph_embedding = L2R;
14445
14446
14447
14448 if (f->n_tab_bar_rows > 0)
14449 {
14450 int border, rows, height, extra;
14451
14452 if (TYPE_RANGED_FIXNUMP (int, Vtab_bar_border))
14453 border = XFIXNUM (Vtab_bar_border);
14454 else if (EQ (Vtab_bar_border, Qinternal_border_width))
14455 border = FRAME_INTERNAL_BORDER_WIDTH (f);
14456 else if (EQ (Vtab_bar_border, Qborder_width))
14457 border = f->border_width;
14458 else
14459 border = 0;
14460 if (border < 0)
14461 border = 0;
14462
14463 rows = f->n_tab_bar_rows;
14464 height = max (1, (it.last_visible_y - border) / rows);
14465 extra = it.last_visible_y - border - height * rows;
14466
14467 while (it.current_y < it.last_visible_y)
14468 {
14469 int h = 0;
14470 if (extra > 0 && rows-- > 0)
14471 {
14472 h = (extra + rows - 1) / rows;
14473 extra -= h;
14474 }
14475 display_tab_bar_line (&it, height + h);
14476 }
14477 }
14478 else
14479 {
14480 while (it.current_y < it.last_visible_y)
14481 display_tab_bar_line (&it, 0);
14482 }
14483
14484
14485
14486 w->desired_matrix->no_scrolling_p = true;
14487 w->must_be_updated_p = true;
14488
14489 if (!NILP (Vauto_resize_tab_bars))
14490 {
14491 bool change_height_p = false;
14492
14493
14494
14495 if (IT_STRING_CHARPOS (it) < it.end_charpos)
14496 change_height_p = true;
14497
14498
14499
14500
14501
14502 row = it.glyph_row - 1;
14503
14504
14505
14506
14507 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14508 && row->height >= FRAME_LINE_HEIGHT (f))
14509 change_height_p = true;
14510
14511
14512
14513 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
14514 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
14515 change_height_p = true;
14516
14517
14518
14519 if (change_height_p)
14520 {
14521 int nrows;
14522 int new_height = tab_bar_height (f, &nrows, true);
14523
14524 change_height_p = ((EQ (Vauto_resize_tab_bars, Qgrow_only)
14525 && !f->minimize_tab_bar_window_p)
14526 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
14527 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
14528 f->minimize_tab_bar_window_p = false;
14529
14530 if (change_height_p)
14531 {
14532 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14533 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14534 frame_default_tab_bar_height = new_height;
14535 clear_glyph_matrix (w->desired_matrix);
14536 f->n_tab_bar_rows = nrows;
14537 f->fonts_changed = true;
14538
14539 return true;
14540 }
14541 }
14542 }
14543
14544 f->minimize_tab_bar_window_p = false;
14545 return false;
14546 }
14547
14548
14549
14550
14551
14552
14553
14554 static bool
14555 tab_bar_item_info (struct frame *f, struct glyph *glyph,
14556 int *prop_idx, bool *close_p)
14557 {
14558 Lisp_Object prop;
14559 ptrdiff_t charpos;
14560
14561
14562
14563
14564 charpos = min (SCHARS (f->current_tab_bar_string), glyph->charpos);
14565 charpos = max (0, charpos);
14566
14567
14568
14569
14570 prop = Fget_text_property (make_fixnum (charpos),
14571 Qmenu_item, f->current_tab_bar_string);
14572 if (! FIXNUMP (prop))
14573 return false;
14574 *prop_idx = XFIXNUM (prop);
14575
14576 *close_p = !NILP (Fget_text_property (make_fixnum (charpos),
14577 Qclose_tab,
14578 f->current_tab_bar_string));
14579
14580 return true;
14581 }
14582
14583
14584
14585
14586
14587
14588
14589
14590
14591
14592
14593
14594 static int
14595 get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
14596 int *hpos, int *vpos, int *prop_idx, bool *close_p)
14597 {
14598 struct window *w = XWINDOW (f->tab_bar_window);
14599 int area;
14600
14601
14602 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
14603 if (*glyph == NULL)
14604 return -1;
14605
14606
14607
14608 if (!tab_bar_item_info (f, *glyph, prop_idx, close_p))
14609 return -1;
14610
14611 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14612 }
14613
14614
14615
14616
14617
14618
14619
14620
14621 Lisp_Object
14622 handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14623 int modifiers)
14624 {
14625 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14626 struct window *w = XWINDOW (f->tab_bar_window);
14627 int hpos, vpos, prop_idx;
14628 bool close_p;
14629 struct glyph *glyph;
14630 Lisp_Object enabled_p;
14631 int ts;
14632
14633 frame_to_window_pixel_xy (w, &x, &y);
14634 ts = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14635 if (ts == -1)
14636 return Fcons (Qtab_bar, Qnil);
14637
14638
14639 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14640 if (NILP (enabled_p))
14641 return Qnil;
14642
14643 if (down_p)
14644 {
14645
14646 if (!NILP (Vmouse_highlight))
14647 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
14648 f->last_tab_bar_item = prop_idx;
14649 }
14650 else
14651 {
14652
14653 if (!NILP (Vmouse_highlight))
14654 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
14655 f->last_tab_bar_item = -1;
14656 }
14657
14658 Lisp_Object caption =
14659 Fcopy_sequence (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION));
14660
14661 AUTO_LIST2 (props, Qmenu_item,
14662 list3 (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_KEY),
14663 AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_BINDING),
14664 close_p ? Qt : Qnil));
14665
14666 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14667 props, caption);
14668
14669 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14670 }
14671
14672
14673
14674
14675
14676
14677 static void
14678 note_tab_bar_highlight (struct frame *f, int x, int y)
14679 {
14680 Lisp_Object window = f->tab_bar_window;
14681 struct window *w = XWINDOW (window);
14682 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14683 int hpos, vpos;
14684 struct glyph *glyph;
14685 struct glyph_row *row;
14686 int i;
14687 Lisp_Object enabled_p;
14688 int prop_idx;
14689 bool close_p;
14690 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
14691 int rc;
14692
14693
14694
14695 if (x <= 0 || y <= 0)
14696 {
14697 clear_mouse_face (hlinfo);
14698 return;
14699 }
14700
14701 rc = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14702 if (rc < 0)
14703 {
14704
14705 clear_mouse_face (hlinfo);
14706 return;
14707 }
14708 else if (rc == 0)
14709
14710 goto set_help_echo;
14711
14712 clear_mouse_face (hlinfo);
14713
14714 bool mouse_down_p = false;
14715
14716
14717
14718
14719
14720 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
14721 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
14722 && f == dpyinfo->last_mouse_frame);
14723
14724 if (mouse_down_p && f->last_tab_bar_item != prop_idx
14725 && f->last_tab_bar_item != -1)
14726 return;
14727 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
14728
14729
14730 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14731 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
14732 {
14733
14734
14735 row = MATRIX_ROW (w->current_matrix, vpos);
14736 for (i = x = 0; i < hpos; ++i)
14737 x += row->glyphs[TEXT_AREA][i].pixel_width;
14738
14739
14740 hlinfo->mouse_face_beg_col = hpos;
14741 hlinfo->mouse_face_beg_row = vpos;
14742 hlinfo->mouse_face_beg_x = x;
14743 hlinfo->mouse_face_past_end = false;
14744
14745 hlinfo->mouse_face_end_col = hpos + 1;
14746 hlinfo->mouse_face_end_row = vpos;
14747 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
14748 hlinfo->mouse_face_window = window;
14749 hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID;
14750
14751
14752 show_mouse_face (hlinfo, draw);
14753 }
14754
14755 set_help_echo:
14756
14757
14758
14759 help_echo_object = help_echo_window = Qnil;
14760 help_echo_pos = -1;
14761 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_HELP);
14762 if (NILP (help_echo_string))
14763 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION);
14764 }
14765
14766 #endif
14767
14768
14769 static Lisp_Object
14770 tty_get_tab_bar_item (struct frame *f, int x, int *prop_idx, bool *close_p)
14771 {
14772 ptrdiff_t clen = 0;
14773
14774 for (int i = 0; i < f->n_tab_bar_items; i++)
14775 {
14776 Lisp_Object caption = AREF (f->tab_bar_items, (i * TAB_BAR_ITEM_NSLOTS
14777 + TAB_BAR_ITEM_CAPTION));
14778 if (NILP (caption))
14779 return Qnil;
14780 clen += SCHARS (caption);
14781 if (x < clen)
14782 {
14783 *prop_idx = i;
14784 *close_p = !NILP (Fget_text_property (make_fixnum (SCHARS (caption)
14785 - (clen - x)),
14786 Qclose_tab,
14787 caption));
14788 return caption;
14789 }
14790 }
14791 return Qnil;
14792 }
14793
14794
14795
14796
14797
14798
14799 Lisp_Object
14800 tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14801 struct input_event *event)
14802 {
14803
14804 if (y < FRAME_MENU_BAR_LINES (f)
14805 || y >= FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f))
14806 return Qnil;
14807
14808
14809 int prop_idx;
14810 bool close_p;
14811 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &close_p);
14812
14813 if (NILP (caption))
14814 return Qnil;
14815
14816 if (NILP (AREF (f->tab_bar_items,
14817 prop_idx * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_ENABLED_P)))
14818 return Qnil;
14819
14820 if (down_p)
14821 f->last_tab_bar_item = prop_idx;
14822 else
14823 f->last_tab_bar_item = -1;
14824
14825 caption = Fcopy_sequence (caption);
14826
14827 AUTO_LIST2 (props, Qmenu_item,
14828 list3 (AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14829 + TAB_BAR_ITEM_KEY),
14830 AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14831 + TAB_BAR_ITEM_BINDING),
14832 close_p ? Qt : Qnil));
14833
14834 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14835 props, caption);
14836
14837 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14838 }
14839
14840
14841
14842
14843
14844
14845
14846 #ifdef HAVE_WINDOW_SYSTEM
14847
14848
14849
14850
14851
14852
14853 static void
14854 update_tool_bar (struct frame *f, bool save_match_data)
14855 {
14856 #ifdef HAVE_EXT_TOOL_BAR
14857 bool do_update = FRAME_EXTERNAL_TOOL_BAR (f);
14858 #else
14859 bool do_update = (WINDOWP (f->tool_bar_window)
14860 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0);
14861 #endif
14862
14863 if (do_update)
14864 {
14865 Lisp_Object window;
14866 struct window *w;
14867
14868 window = FRAME_SELECTED_WINDOW (f);
14869 w = XWINDOW (window);
14870
14871
14872
14873
14874
14875
14876
14877
14878 if (windows_or_buffers_changed
14879 || w->update_mode_line
14880 || update_mode_lines
14881 || window_buffer_changed (w))
14882 {
14883 struct buffer *prev = current_buffer;
14884 specpdl_ref count = SPECPDL_INDEX ();
14885 Lisp_Object frame, new_tool_bar;
14886 int new_n_tool_bar;
14887
14888
14889
14890
14891 set_buffer_internal_1 (XBUFFER (w->contents));
14892
14893
14894 if (save_match_data)
14895 record_unwind_save_match_data ();
14896
14897
14898 if (NILP (Voverriding_local_map_menu_flag))
14899 {
14900 specbind (Qoverriding_terminal_local_map, Qnil);
14901 specbind (Qoverriding_local_map, Qnil);
14902 }
14903
14904
14905
14906
14907
14908 eassert (EQ (selected_window,
14909
14910
14911 XFRAME (selected_frame)->selected_window));
14912 record_unwind_protect (restore_selected_window, selected_window);
14913 XSETFRAME (frame, f);
14914 selected_frame = frame;
14915 selected_window = FRAME_SELECTED_WINDOW (f);
14916
14917
14918 new_tool_bar
14919 = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
14920 &new_n_tool_bar);
14921
14922
14923 if (new_n_tool_bar != f->n_tool_bar_items
14924 || NILP (Fequal (new_tool_bar, f->tool_bar_items)))
14925 {
14926
14927
14928
14929 block_input ();
14930 fset_tool_bar_items (f, new_tool_bar);
14931 f->n_tool_bar_items = new_n_tool_bar;
14932 w->update_mode_line = true;
14933 unblock_input ();
14934 }
14935
14936 unbind_to (count, Qnil);
14937 set_buffer_internal_1 (prev);
14938 }
14939 }
14940 }
14941
14942 #ifndef HAVE_EXT_TOOL_BAR
14943
14944
14945
14946
14947
14948 static void
14949 build_desired_tool_bar_string (struct frame *f)
14950 {
14951 int i, size, size_needed;
14952 Lisp_Object image, plist;
14953
14954 image = plist = Qnil;
14955
14956
14957
14958
14959
14960 size = (STRINGP (f->desired_tool_bar_string)
14961 ? SCHARS (f->desired_tool_bar_string)
14962 : 0);
14963
14964
14965 size_needed = f->n_tool_bar_items;
14966
14967
14968 if (size < size_needed || NILP (f->desired_tool_bar_string))
14969 fset_desired_tool_bar_string
14970 (f, Fmake_string (make_fixnum (size_needed), make_fixnum (' '), Qnil));
14971 else
14972 {
14973 AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil);
14974 Fremove_text_properties (make_fixnum (0), make_fixnum (size),
14975 props, f->desired_tool_bar_string);
14976 }
14977
14978
14979
14980
14981 for (i = 0; i < f->n_tool_bar_items; ++i)
14982 {
14983 #define PROP(IDX) \
14984 AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
14985
14986 bool enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
14987 bool selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
14988 int hmargin, vmargin, relief, idx, end;
14989
14990
14991
14992 image = PROP (TOOL_BAR_ITEM_IMAGES);
14993 if (VECTORP (image))
14994 {
14995 if (enabled_p)
14996 idx = (selected_p
14997 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
14998 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
14999 else
15000 idx = (selected_p
15001 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
15002 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
15003
15004 eassert (ASIZE (image) >= idx);
15005 image = AREF (image, idx);
15006 }
15007 else
15008 idx = -1;
15009
15010
15011 if (!valid_image_p (image))
15012 continue;
15013
15014
15015 plist = Fcopy_sequence (XCDR (image));
15016
15017
15018 relief = (tool_bar_button_relief >= 0
15019 ? min (tool_bar_button_relief,
15020 min (INT_MAX, MOST_POSITIVE_FIXNUM))
15021 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
15022 hmargin = vmargin = relief;
15023
15024 if (RANGED_FIXNUMP (1, Vtool_bar_button_margin,
15025 INT_MAX - max (hmargin, vmargin)))
15026 {
15027 hmargin += XFIXNAT (Vtool_bar_button_margin);
15028 vmargin += XFIXNAT (Vtool_bar_button_margin);
15029 }
15030 else if (CONSP (Vtool_bar_button_margin))
15031 {
15032 if (RANGED_FIXNUMP (1, XCAR (Vtool_bar_button_margin),
15033 INT_MAX - hmargin))
15034 hmargin += XFIXNAT (XCAR (Vtool_bar_button_margin));
15035
15036 if (RANGED_FIXNUMP (1, XCDR (Vtool_bar_button_margin),
15037 INT_MAX - vmargin))
15038 vmargin += XFIXNAT (XCDR (Vtool_bar_button_margin));
15039 }
15040
15041 if (auto_raise_tool_bar_buttons_p)
15042 {
15043
15044
15045 if (selected_p)
15046 {
15047 plist = plist_put (plist, QCrelief, make_fixnum (-relief));
15048 hmargin -= relief;
15049 vmargin -= relief;
15050 }
15051 }
15052 else
15053 {
15054
15055
15056
15057 plist = plist_put (plist, QCrelief,
15058 (selected_p
15059 ? make_fixnum (-relief)
15060 : make_fixnum (relief)));
15061 hmargin -= relief;
15062 vmargin -= relief;
15063 }
15064
15065
15066 if (hmargin || vmargin)
15067 {
15068 if (hmargin == vmargin)
15069 plist = plist_put (plist, QCmargin, make_fixnum (hmargin));
15070 else
15071 plist = plist_put (plist, QCmargin,
15072 Fcons (make_fixnum (hmargin),
15073 make_fixnum (vmargin)));
15074 }
15075
15076
15077
15078
15079 if (!enabled_p && idx < 0)
15080 plist = plist_put (plist, QCconversion, Qdisabled);
15081
15082
15083
15084
15085
15086 image = Fcons (Qimage, plist);
15087 AUTO_LIST4 (props, Qdisplay, image, Qmenu_item,
15088 make_fixnum (i * TOOL_BAR_ITEM_NSLOTS));
15089
15090
15091
15092
15093 if (i + 1 == f->n_tool_bar_items)
15094 end = SCHARS (f->desired_tool_bar_string);
15095 else
15096 end = i + 1;
15097 Fadd_text_properties (make_fixnum (i), make_fixnum (end),
15098 props, f->desired_tool_bar_string);
15099 #undef PROP
15100 }
15101 }
15102
15103
15104
15105
15106
15107
15108
15109
15110
15111
15112
15113
15114
15115
15116 static void
15117 display_tool_bar_line (struct it *it, int height)
15118 {
15119 struct glyph_row *row = it->glyph_row;
15120 int max_x = it->last_visible_x;
15121 struct glyph *last;
15122
15123
15124 clear_glyph_row (row);
15125 row->enabled_p = true;
15126 row->y = it->current_y;
15127
15128
15129
15130 it->start_of_box_run_p = true;
15131
15132 while (it->current_x < max_x)
15133 {
15134 int x, n_glyphs_before, i, nglyphs;
15135 struct it it_before;
15136
15137
15138 if (!get_next_display_element (it))
15139 {
15140
15141 if (height < 0 && !it->hpos)
15142 return;
15143 break;
15144 }
15145
15146
15147 n_glyphs_before = row->used[TEXT_AREA];
15148 it_before = *it;
15149
15150 PRODUCE_GLYPHS (it);
15151
15152 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
15153 i = 0;
15154 x = it_before.current_x;
15155 while (i < nglyphs)
15156 {
15157 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
15158
15159 if (x + glyph->pixel_width > max_x)
15160 {
15161
15162 row->used[TEXT_AREA] = n_glyphs_before;
15163 *it = it_before;
15164
15165
15166
15167 if (n_glyphs_before == 0
15168 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
15169 break;
15170 goto out;
15171 }
15172
15173 ++it->hpos;
15174 x += glyph->pixel_width;
15175 ++i;
15176 }
15177
15178
15179 if (ITERATOR_AT_END_OF_LINE_P (it))
15180 break;
15181
15182 set_iterator_to_next (it, true);
15183 }
15184
15185 out:;
15186
15187 row->displays_text_p = row->used[TEXT_AREA] != 0;
15188
15189
15190
15191
15192
15193
15194
15195 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15196 && !EQ (Vauto_resize_tool_bars, Qgrow_only))
15197 it->face_id = DEFAULT_FACE_ID;
15198
15199 extend_face_to_end_of_line (it);
15200 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
15201 last->right_box_line_p = true;
15202 if (last == row->glyphs[TEXT_AREA])
15203 last->left_box_line_p = true;
15204
15205
15206 if ((height -= it->max_ascent + it->max_descent) > 0)
15207 {
15208
15209 height %= FRAME_LINE_HEIGHT (it->f);
15210 it->max_ascent += height / 2;
15211 it->max_descent += (height + 1) / 2;
15212 }
15213
15214 compute_line_metrics (it);
15215
15216
15217 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
15218 {
15219 row->height = row->phys_height = it->last_visible_y - row->y;
15220 row->visible_height = row->height;
15221 row->ascent = row->phys_ascent = 0;
15222 row->extra_line_spacing = 0;
15223 }
15224
15225 row->full_width_p = true;
15226 row->continued_p = false;
15227 row->truncated_on_left_p = false;
15228 row->truncated_on_right_p = false;
15229
15230 it->current_x = it->hpos = 0;
15231 it->current_y += row->height;
15232 ++it->vpos;
15233 ++it->glyph_row;
15234 }
15235
15236
15237
15238
15239
15240 static int
15241 tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
15242 {
15243 struct window *w = XWINDOW (f->tool_bar_window);
15244 struct it it;
15245
15246
15247
15248 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
15249
15250
15251
15252 init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
15253 temp_row->reversed_p = false;
15254 it.first_visible_x = 0;
15255 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15256 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15257 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15258 it.paragraph_embedding = L2R;
15259
15260 while (!ITERATOR_AT_END_P (&it))
15261 {
15262 clear_glyph_row (temp_row);
15263 it.glyph_row = temp_row;
15264 display_tool_bar_line (&it, -1);
15265 }
15266 clear_glyph_row (temp_row);
15267
15268
15269 if (n_rows)
15270 *n_rows = it.vpos > 0 ? it.vpos : -1;
15271
15272 if (pixelwise)
15273 return it.current_y;
15274 else
15275 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
15276 }
15277
15278 #endif
15279
15280 DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
15281 0, 2, 0,
15282 doc:
15283
15284 )
15285 (Lisp_Object frame, Lisp_Object pixelwise)
15286 {
15287 int height = 0;
15288
15289 #ifndef HAVE_EXT_TOOL_BAR
15290 struct frame *f = decode_any_frame (frame);
15291
15292 if (WINDOWP (f->tool_bar_window)
15293 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0)
15294 {
15295 update_tool_bar (f, true);
15296 if (f->n_tool_bar_items)
15297 {
15298 build_desired_tool_bar_string (f);
15299 height = tool_bar_height (f, NULL, !NILP (pixelwise));
15300 }
15301 }
15302 #endif
15303
15304 return make_fixnum (height);
15305 }
15306
15307 #ifndef HAVE_EXT_TOOL_BAR
15308
15309
15310
15311 static bool
15312 redisplay_tool_bar (struct frame *f)
15313 {
15314 struct window *w;
15315 struct it it;
15316 struct glyph_row *row;
15317
15318 f->tool_bar_redisplayed = true;
15319
15320
15321
15322
15323
15324 if (!WINDOWP (f->tool_bar_window)
15325 || (w = XWINDOW (f->tool_bar_window),
15326 WINDOW_TOTAL_LINES (w) == 0))
15327 {
15328
15329
15330
15331
15332
15333 f->tool_bar_resized = true;
15334
15335 return false;
15336 }
15337
15338
15339 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
15340 it.first_visible_x = 0;
15341 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15342 row = it.glyph_row;
15343 row->reversed_p = false;
15344
15345
15346 build_desired_tool_bar_string (f);
15347 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15348 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15349
15350
15351
15352
15353
15354
15355
15356 it.paragraph_embedding = L2R;
15357
15358 if (f->n_tool_bar_rows == 0)
15359 {
15360 int new_height = tool_bar_height (f, &f->n_tool_bar_rows, true);
15361
15362 if (new_height != WINDOW_PIXEL_HEIGHT (w))
15363 {
15364 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15365 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15366 frame_default_tool_bar_height = new_height;
15367
15368 clear_glyph_matrix (w->desired_matrix);
15369 f->fonts_changed = true;
15370 return true;
15371 }
15372 }
15373
15374
15375
15376 if (f->n_tool_bar_rows > 0)
15377 {
15378 int border, rows, height, extra;
15379
15380 if (TYPE_RANGED_FIXNUMP (int, Vtool_bar_border))
15381 border = XFIXNUM (Vtool_bar_border);
15382 else if (EQ (Vtool_bar_border, Qinternal_border_width))
15383 border = FRAME_INTERNAL_BORDER_WIDTH (f);
15384 else if (EQ (Vtool_bar_border, Qborder_width))
15385 border = f->border_width;
15386 else
15387 border = 0;
15388 if (border < 0)
15389 border = 0;
15390
15391 rows = f->n_tool_bar_rows;
15392 height = max (1, (it.last_visible_y - border) / rows);
15393 extra = it.last_visible_y - border - height * rows;
15394
15395 while (it.current_y < it.last_visible_y)
15396 {
15397 int h = 0;
15398 if (extra > 0 && rows-- > 0)
15399 {
15400 h = (extra + rows - 1) / rows;
15401 extra -= h;
15402 }
15403 display_tool_bar_line (&it, height + h);
15404 }
15405 }
15406 else
15407 {
15408 while (it.current_y < it.last_visible_y)
15409 display_tool_bar_line (&it, 0);
15410 }
15411
15412
15413
15414 w->desired_matrix->no_scrolling_p = true;
15415 w->must_be_updated_p = true;
15416
15417 if (!NILP (Vauto_resize_tool_bars))
15418 {
15419 bool change_height_p = false;
15420
15421
15422
15423 if (IT_STRING_CHARPOS (it) < it.end_charpos)
15424 change_height_p = true;
15425
15426
15427
15428
15429
15430 row = it.glyph_row - 1;
15431
15432
15433
15434
15435 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15436 && row->height >= FRAME_LINE_HEIGHT (f))
15437 change_height_p = true;
15438
15439
15440
15441 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
15442 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
15443 change_height_p = true;
15444
15445
15446
15447 if (change_height_p)
15448 {
15449 int nrows;
15450 int new_height = tool_bar_height (f, &nrows, true);
15451
15452 change_height_p = ((EQ (Vauto_resize_tool_bars, Qgrow_only)
15453 && !f->minimize_tool_bar_window_p)
15454 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
15455 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
15456 f->minimize_tool_bar_window_p = false;
15457
15458 if (change_height_p)
15459 {
15460 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15461 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15462 frame_default_tool_bar_height = new_height;
15463 clear_glyph_matrix (w->desired_matrix);
15464 f->n_tool_bar_rows = nrows;
15465 f->fonts_changed = true;
15466
15467 return true;
15468 }
15469 }
15470 }
15471
15472 f->minimize_tool_bar_window_p = false;
15473
15474 return false;
15475 }
15476
15477
15478
15479
15480
15481
15482 static bool
15483 tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx)
15484 {
15485 Lisp_Object prop;
15486 ptrdiff_t charpos;
15487
15488
15489
15490
15491 charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
15492 charpos = max (0, charpos);
15493
15494
15495
15496
15497 prop = Fget_text_property (make_fixnum (charpos),
15498 Qmenu_item, f->current_tool_bar_string);
15499 if (! FIXNUMP (prop))
15500 return false;
15501 *prop_idx = XFIXNUM (prop);
15502 return true;
15503 }
15504
15505
15506
15507
15508
15509
15510
15511
15512
15513
15514
15515
15516 static int
15517 get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
15518 int *hpos, int *vpos, int *prop_idx)
15519 {
15520 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15521 struct window *w = XWINDOW (f->tool_bar_window);
15522 int area;
15523
15524
15525 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
15526 if (*glyph == NULL)
15527 return -1;
15528
15529
15530
15531 if (!tool_bar_item_info (f, *glyph, prop_idx))
15532 return -1;
15533
15534
15535 if (EQ (f->tool_bar_window, hlinfo->mouse_face_window)
15536 && *vpos >= hlinfo->mouse_face_beg_row
15537 && *vpos <= hlinfo->mouse_face_end_row
15538 && (*vpos > hlinfo->mouse_face_beg_row
15539 || *hpos >= hlinfo->mouse_face_beg_col)
15540 && (*vpos < hlinfo->mouse_face_end_row
15541 || *hpos < hlinfo->mouse_face_end_col
15542 || hlinfo->mouse_face_past_end))
15543 return 0;
15544
15545 return 1;
15546 }
15547
15548
15549
15550
15551
15552
15553
15554
15555 void
15556 handle_tool_bar_click_with_device (struct frame *f, int x, int y, bool down_p,
15557 int modifiers, Lisp_Object device)
15558 {
15559 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15560 struct window *w = XWINDOW (f->tool_bar_window);
15561 int hpos, vpos, prop_idx;
15562 struct glyph *glyph;
15563 Lisp_Object enabled_p;
15564 int ts;
15565
15566
15567
15568
15569
15570
15571
15572
15573 frame_to_window_pixel_xy (w, &x, &y);
15574 ts = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15575 if (ts == -1
15576 || (ts != 0 && !NILP (Vmouse_highlight)))
15577 return;
15578
15579
15580
15581
15582 if (NILP (Vmouse_highlight) && !down_p)
15583 prop_idx = f->last_tool_bar_item;
15584
15585
15586 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15587 if (NILP (enabled_p))
15588 return;
15589
15590 if (down_p)
15591 {
15592
15593 if (!NILP (Vmouse_highlight))
15594 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
15595 f->last_tool_bar_item = prop_idx;
15596 }
15597 else
15598 {
15599 Lisp_Object key, frame;
15600 struct input_event event;
15601 EVENT_INIT (event);
15602
15603
15604 if (!NILP (Vmouse_highlight))
15605 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
15606
15607 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
15608
15609 XSETFRAME (frame, f);
15610 event.kind = TOOL_BAR_EVENT;
15611 event.frame_or_window = frame;
15612 event.arg = key;
15613 event.modifiers = modifiers;
15614 event.device = device;
15615 kbd_buffer_store_event (&event);
15616 f->last_tool_bar_item = -1;
15617 }
15618 }
15619
15620 void
15621 handle_tool_bar_click (struct frame *f, int x, int y, bool down_p,
15622 int modifiers)
15623 {
15624 handle_tool_bar_click_with_device (f, x, y, down_p, modifiers, Qt);
15625 }
15626
15627
15628
15629
15630
15631 static void
15632 note_tool_bar_highlight (struct frame *f, int x, int y)
15633 {
15634 Lisp_Object window = f->tool_bar_window;
15635 struct window *w = XWINDOW (window);
15636 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
15637 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15638 int hpos, vpos;
15639 struct glyph *glyph;
15640 struct glyph_row *row;
15641 int i;
15642 Lisp_Object enabled_p;
15643 int prop_idx;
15644 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
15645 bool mouse_down_p;
15646 int rc;
15647
15648
15649
15650 if (x <= 0 || y <= 0)
15651 {
15652 clear_mouse_face (hlinfo);
15653 return;
15654 }
15655
15656 rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15657 if (rc < 0)
15658 {
15659
15660 clear_mouse_face (hlinfo);
15661 return;
15662 }
15663 else if (rc == 0)
15664
15665 goto set_help_echo;
15666
15667 clear_mouse_face (hlinfo);
15668
15669
15670 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
15671 && f == dpyinfo->last_mouse_frame);
15672
15673 if (mouse_down_p && f->last_tool_bar_item != prop_idx)
15674 return;
15675
15676 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
15677
15678
15679 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15680 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
15681 {
15682
15683
15684 row = MATRIX_ROW (w->current_matrix, vpos);
15685 for (i = x = 0; i < hpos; ++i)
15686 x += row->glyphs[TEXT_AREA][i].pixel_width;
15687
15688
15689 hlinfo->mouse_face_beg_col = hpos;
15690 hlinfo->mouse_face_beg_row = vpos;
15691 hlinfo->mouse_face_beg_x = x;
15692 hlinfo->mouse_face_past_end = false;
15693
15694 hlinfo->mouse_face_end_col = hpos + 1;
15695 hlinfo->mouse_face_end_row = vpos;
15696 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
15697 hlinfo->mouse_face_window = window;
15698 hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
15699
15700
15701 show_mouse_face (hlinfo, draw);
15702 }
15703
15704 set_help_echo:
15705
15706
15707
15708 help_echo_object = help_echo_window = Qnil;
15709 help_echo_pos = -1;
15710 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
15711 if (NILP (help_echo_string))
15712 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
15713 }
15714
15715 #endif
15716
15717 #endif
15718
15719
15720
15721
15722
15723
15724
15725
15726
15727
15728
15729
15730
15731 static bool
15732 hscroll_window_tree (Lisp_Object window)
15733 {
15734 bool hscrolled_p = false;
15735 bool hscroll_relative_p = FLOATP (Vhscroll_step);
15736 int hscroll_step_abs = 0;
15737 double hscroll_step_rel = 0;
15738
15739 if (hscroll_relative_p)
15740 {
15741 hscroll_step_rel = XFLOAT_DATA (Vhscroll_step);
15742 if (hscroll_step_rel < 0)
15743 {
15744 hscroll_relative_p = false;
15745 hscroll_step_abs = 0;
15746 }
15747 }
15748 else if (TYPE_RANGED_FIXNUMP (int, Vhscroll_step))
15749 {
15750 hscroll_step_abs = XFIXNUM (Vhscroll_step);
15751 if (hscroll_step_abs < 0)
15752 hscroll_step_abs = 0;
15753 }
15754 else
15755 hscroll_step_abs = 0;
15756
15757 while (WINDOWP (window))
15758 {
15759 struct window *w = XWINDOW (window);
15760
15761 if (WINDOWP (w->contents))
15762 hscrolled_p |= hscroll_window_tree (w->contents);
15763 else if (w->cursor.vpos >= 0
15764
15765
15766
15767
15768
15769
15770 && !(w == XWINDOW (echo_area_window)
15771 && !NILP (echo_area_buffer[0])))
15772 {
15773 int h_margin;
15774 int text_area_width;
15775 struct glyph_row *cursor_row;
15776 struct glyph_row *bottom_row;
15777
15778 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w);
15779 if (w->cursor.vpos < bottom_row - w->desired_matrix->rows)
15780 cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
15781 else
15782 cursor_row = bottom_row - 1;
15783
15784 if (!cursor_row->enabled_p)
15785 {
15786 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
15787 if (w->cursor.vpos < bottom_row - w->current_matrix->rows)
15788 cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
15789 else
15790 cursor_row = bottom_row - 1;
15791 }
15792 bool row_r2l_p = cursor_row->reversed_p;
15793 bool hscl = hscrolling_current_line_p (w);
15794 int x_offset = 0;
15795
15796
15797 if (!NILP (Vdisplay_line_numbers))
15798 {
15799 struct glyph *g;
15800 if (!row_r2l_p)
15801 {
15802 for (g = cursor_row->glyphs[TEXT_AREA];
15803 g < cursor_row->glyphs[TEXT_AREA]
15804 + cursor_row->used[TEXT_AREA];
15805 g++)
15806 {
15807 if (!(NILP (g->object) && g->charpos < 0))
15808 break;
15809 x_offset += g->pixel_width;
15810 }
15811 }
15812 else
15813 {
15814 for (g = cursor_row->glyphs[TEXT_AREA]
15815 + cursor_row->used[TEXT_AREA];
15816 g > cursor_row->glyphs[TEXT_AREA];
15817 g--)
15818 {
15819 if (!(NILP ((g - 1)->object) && (g - 1)->charpos < 0))
15820 break;
15821 x_offset += (g - 1)->pixel_width;
15822 }
15823 }
15824 }
15825 if (cursor_row->truncated_on_left_p)
15826 {
15827
15828 struct frame *f = XFRAME (WINDOW_FRAME (w));
15829 x_offset -= (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
15830 }
15831
15832 text_area_width = window_box_width (w, TEXT_AREA);
15833
15834
15835 h_margin = (clip_to_bounds (0, hscroll_margin, 1000000)
15836 * WINDOW_FRAME_COLUMN_WIDTH (w));
15837
15838
15839
15840 if (w->suspend_auto_hscroll
15841 && NILP (Fequal (Fwindow_point (window),
15842 Fwindow_old_point (window))))
15843 {
15844 w->suspend_auto_hscroll = false;
15845
15846
15847
15848
15849 if (w->min_hscroll == 0 && w->hscroll > 0
15850 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
15851 Qcurrent_line))
15852 SET_FRAME_GARBAGED (XFRAME (w->frame));
15853 }
15854
15855
15856 Fset_marker (w->old_pointm,
15857 ((w == XWINDOW (selected_window))
15858 ? make_fixnum (BUF_PT (XBUFFER (w->contents)))
15859 : Fmarker_position (w->pointm)),
15860 w->contents);
15861
15862 if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents))
15863 && !w->suspend_auto_hscroll
15864
15865
15866
15867
15868
15869
15870 && (CHARPOS (cursor_row->start.pos)
15871 >= BUF_BEG (XBUFFER (w->contents)))
15872
15873
15874
15875
15876 && ((!row_r2l_p
15877 && ((w->hscroll && w->cursor.x <= h_margin + x_offset)
15878 || (cursor_row->enabled_p
15879 && cursor_row->truncated_on_right_p
15880 && (w->cursor.x >= text_area_width - h_margin))))
15881
15882
15883
15884
15885
15886
15887 || (row_r2l_p
15888 && ((cursor_row->enabled_p
15889
15890
15891
15892 && cursor_row->truncated_on_right_p
15893 && w->cursor.x <= h_margin)
15894 || (w->hscroll
15895 && (w->cursor.x >= (text_area_width - h_margin
15896 - x_offset)))))
15897
15898
15899
15900
15901
15902 || (hscl
15903 && w->hscroll != w->min_hscroll
15904 && !cursor_row->truncated_on_left_p)))
15905 {
15906 struct it it;
15907 ptrdiff_t hscroll;
15908 struct buffer *saved_current_buffer;
15909 ptrdiff_t pt;
15910 int wanted_x;
15911
15912
15913 saved_current_buffer = current_buffer;
15914 current_buffer = XBUFFER (w->contents);
15915
15916 if (w == XWINDOW (selected_window))
15917 pt = PT;
15918 else
15919 pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
15920
15921
15922
15923 init_to_row_start (&it, w, cursor_row);
15924 if (hscl)
15925 it.first_visible_x = window_hscroll_limited (w, it.f)
15926 * FRAME_COLUMN_WIDTH (it.f);
15927 it.last_visible_x = DISP_INFINITY;
15928
15929 ptrdiff_t nchars = pt - IT_CHARPOS (it);
15930 if (current_buffer->long_line_optimizations_p
15931 && nchars > large_hscroll_threshold)
15932 {
15933
15934
15935
15936
15937 fast_move_it_horizontally (&it, nchars);
15938 it.current_x += nchars * FRAME_COLUMN_WIDTH (it.f);
15939 }
15940 else
15941 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
15942
15943
15944
15945
15946
15947
15948 if (it.method == GET_FROM_STRING && pt > 1)
15949 {
15950 init_to_row_start (&it, w, cursor_row);
15951 if (hscl)
15952 it.first_visible_x = (window_hscroll_limited (w, it.f)
15953 * FRAME_COLUMN_WIDTH (it.f));
15954 if (current_buffer->long_line_optimizations_p
15955 && nchars > large_hscroll_threshold)
15956 {
15957 fast_move_it_horizontally (&it, nchars - 1);
15958 it.current_x += (nchars - 1) * FRAME_COLUMN_WIDTH (it.f);
15959 }
15960 else
15961 move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS);
15962 }
15963 current_buffer = saved_current_buffer;
15964
15965
15966 if (!hscroll_relative_p && hscroll_step_abs == 0)
15967 hscroll = max (0, (it.current_x
15968 - (ITERATOR_AT_END_OF_LINE_P (&it)
15969 ? (text_area_width - 4 * FRAME_COLUMN_WIDTH (it.f))
15970 : (text_area_width / 2))))
15971 / FRAME_COLUMN_WIDTH (it.f);
15972 else if ((!row_r2l_p
15973 && w->cursor.x >= text_area_width - h_margin)
15974 || (row_r2l_p && w->cursor.x <= h_margin))
15975 {
15976 if (hscroll_relative_p)
15977 wanted_x = text_area_width * (1 - hscroll_step_rel)
15978 - h_margin;
15979 else
15980 wanted_x = text_area_width
15981 - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
15982 - h_margin;
15983 hscroll
15984 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
15985 }
15986 else
15987 {
15988 if (hscroll_relative_p)
15989 wanted_x =
15990 text_area_width * hscroll_step_rel + h_margin + x_offset;
15991 else
15992 wanted_x =
15993 hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
15994 + h_margin + x_offset;
15995 hscroll
15996 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
15997 }
15998 hscroll = max (hscroll, w->min_hscroll);
15999
16000
16001
16002
16003 if (w->hscroll != hscroll
16004
16005
16006
16007
16008 || (hscl && w->last_cursor_vpos != w->cursor.vpos))
16009 {
16010 struct buffer *b = XBUFFER (w->contents);
16011 b->prevent_redisplay_optimizations_p = true;
16012 w->hscroll = hscroll;
16013 hscrolled_p = true;
16014 }
16015 }
16016 }
16017
16018 window = w->next;
16019 }
16020
16021
16022 return hscrolled_p;
16023 }
16024
16025
16026
16027
16028
16029
16030
16031
16032 static bool
16033 hscroll_windows (Lisp_Object window)
16034 {
16035 bool hscrolled_p = hscroll_window_tree (window);
16036 if (hscrolled_p)
16037 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
16038 return hscrolled_p;
16039 }
16040
16041
16042
16043
16044
16045
16046
16047
16048
16049
16050 #ifdef GLYPH_DEBUG
16051
16052
16053
16054 static int debug_first_unchanged_at_end_vpos;
16055 static int debug_last_unchanged_at_beg_vpos;
16056
16057
16058
16059 static int debug_dvpos, debug_dy;
16060
16061
16062
16063 static ptrdiff_t debug_delta, debug_delta_bytes;
16064
16065
16066
16067
16068 static ptrdiff_t debug_end_vpos;
16069
16070
16071
16072
16073
16074 static void debug_method_add (struct window *, char const *, ...)
16075 ATTRIBUTE_FORMAT_PRINTF (2, 3);
16076
16077 static void
16078 debug_method_add (struct window *w, char const *fmt, ...)
16079 {
16080 void *ptr = w;
16081 char *method = w->desired_matrix->method;
16082 int len = strlen (method);
16083 int size = sizeof w->desired_matrix->method;
16084 int remaining = size - len - 1;
16085 va_list ap;
16086
16087 if (len && remaining)
16088 {
16089 method[len] = '|';
16090 --remaining, ++len;
16091 }
16092
16093 va_start (ap, fmt);
16094 vsnprintf (method + len, remaining + 1, fmt, ap);
16095 va_end (ap);
16096
16097 if (trace_redisplay_p)
16098 fprintf (stderr, "%p (%s): %s\n",
16099 ptr,
16100 ((BUFFERP (w->contents)
16101 && STRINGP (BVAR (XBUFFER (w->contents), name)))
16102 ? SSDATA (BVAR (XBUFFER (w->contents), name))
16103 : "no buffer"),
16104 method + len);
16105 }
16106
16107 #endif
16108
16109
16110
16111
16112
16113
16114
16115 static bool
16116 text_outside_line_unchanged_p (struct window *w,
16117 ptrdiff_t start, ptrdiff_t end)
16118 {
16119 bool unchanged_p = true;
16120
16121
16122 if (window_outdated (w))
16123 {
16124
16125 if (GPT < start || Z - GPT < end)
16126 unchanged_p = false;
16127
16128
16129 if (unchanged_p
16130 && (BEG_UNCHANGED < start - 1
16131 || END_UNCHANGED < end))
16132 unchanged_p = false;
16133
16134
16135
16136 if (unchanged_p
16137 && FIXNUMP (BVAR (current_buffer, selective_display))
16138 && XFIXNUM (BVAR (current_buffer, selective_display)) > 0
16139 && (BEG_UNCHANGED < start || GPT <= start))
16140 unchanged_p = false;
16141
16142
16143
16144
16145
16146
16147
16148
16149 if (unchanged_p)
16150 {
16151 if (BEG + BEG_UNCHANGED == start
16152 && overlay_touches_p (start))
16153 unchanged_p = false;
16154 if (END_UNCHANGED == end
16155 && overlay_touches_p (Z - end))
16156 unchanged_p = false;
16157 }
16158
16159
16160
16161
16162
16163
16164
16165
16166 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
16167 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
16168 unchanged_p = false;
16169 }
16170
16171 return unchanged_p;
16172 }
16173
16174
16175
16176
16177
16178
16179
16180
16181
16182 void
16183 redisplay (void)
16184 {
16185 redisplay_internal ();
16186 }
16187
16188
16189 static Lisp_Object
16190 overlay_arrow_string_or_property (Lisp_Object var)
16191 {
16192 Lisp_Object val;
16193
16194 if (val = Fget (var, Qoverlay_arrow_string), STRINGP (val))
16195 return val;
16196
16197 return Voverlay_arrow_string;
16198 }
16199
16200
16201 static bool
16202 overlay_arrow_in_current_buffer_p (void)
16203 {
16204 Lisp_Object vlist;
16205
16206 for (vlist = Voverlay_arrow_variable_list;
16207 CONSP (vlist);
16208 vlist = XCDR (vlist))
16209 {
16210 Lisp_Object var = XCAR (vlist);
16211 Lisp_Object val;
16212
16213 if (!SYMBOLP (var))
16214 continue;
16215 val = find_symbol_value (var);
16216 if (MARKERP (val)
16217 && current_buffer == XMARKER (val)->buffer)
16218 return true;
16219 }
16220 return false;
16221 }
16222
16223
16224
16225
16226
16227
16228
16229 static bool
16230 overlay_arrows_changed_p (bool set_redisplay)
16231 {
16232 Lisp_Object vlist;
16233 bool changed = false;
16234
16235 for (vlist = Voverlay_arrow_variable_list;
16236 CONSP (vlist);
16237 vlist = XCDR (vlist))
16238 {
16239 Lisp_Object var = XCAR (vlist);
16240 Lisp_Object val, pstr;
16241
16242 if (!SYMBOLP (var))
16243 continue;
16244 val = find_symbol_value (var);
16245 if (!MARKERP (val))
16246 continue;
16247 if (! EQ (Fmarker_position (val),
16248
16249
16250 Fget (var, Qlast_arrow_position))
16251 || ! (pstr = overlay_arrow_string_or_property (var),
16252 EQ (pstr, Fget (var, Qlast_arrow_string))))
16253 {
16254 struct buffer *buf = XMARKER (val)->buffer;
16255
16256 if (set_redisplay)
16257 {
16258 if (buf)
16259 bset_redisplay (buf);
16260 changed = true;
16261 }
16262 else
16263 return true;
16264 }
16265 }
16266 return changed;
16267 }
16268
16269
16270
16271 static void
16272 update_overlay_arrows (int up_to_date)
16273 {
16274 Lisp_Object vlist;
16275
16276 for (vlist = Voverlay_arrow_variable_list;
16277 CONSP (vlist);
16278 vlist = XCDR (vlist))
16279 {
16280 Lisp_Object var = XCAR (vlist);
16281
16282 if (!SYMBOLP (var))
16283 continue;
16284
16285 if (up_to_date > 0)
16286 {
16287 Lisp_Object val = find_symbol_value (var);
16288 if (!MARKERP (val))
16289 continue;
16290 Fput (var, Qlast_arrow_position, Fmarker_position (val));
16291 Fput (var, Qlast_arrow_string,
16292 overlay_arrow_string_or_property (var));
16293 }
16294 else if (up_to_date < 0
16295 || !NILP (Fget (var, Qlast_arrow_position)))
16296 {
16297 Fput (var, Qlast_arrow_position, Qt);
16298 Fput (var, Qlast_arrow_string, Qt);
16299 }
16300 }
16301 }
16302
16303
16304
16305
16306
16307
16308 static Lisp_Object
16309 overlay_arrow_at_row (struct it *it, struct glyph_row *row)
16310 {
16311 Lisp_Object vlist;
16312
16313 for (vlist = Voverlay_arrow_variable_list;
16314 CONSP (vlist);
16315 vlist = XCDR (vlist))
16316 {
16317 Lisp_Object var = XCAR (vlist);
16318 Lisp_Object val;
16319
16320 if (!SYMBOLP (var))
16321 continue;
16322
16323 val = find_symbol_value (var);
16324
16325 if (MARKERP (val)
16326 && current_buffer == XMARKER (val)->buffer
16327 && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
16328 {
16329 if (FRAME_WINDOW_P (it->f)
16330
16331
16332 && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
16333 {
16334 #ifdef HAVE_WINDOW_SYSTEM
16335 if (val = Fget (var, Qoverlay_arrow_bitmap), SYMBOLP (val))
16336 {
16337 int fringe_bitmap = lookup_fringe_bitmap (val);
16338 if (fringe_bitmap != 0)
16339 return make_fixnum (fringe_bitmap);
16340 }
16341 #endif
16342 return make_fixnum (-1);
16343 }
16344 return overlay_arrow_string_or_property (var);
16345 }
16346 }
16347
16348 return Qnil;
16349 }
16350
16351
16352
16353
16354
16355 static bool
16356 check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
16357 struct buffer *buf, ptrdiff_t pt)
16358 {
16359 ptrdiff_t start, end;
16360 Lisp_Object prop;
16361 Lisp_Object buffer;
16362
16363 XSETBUFFER (buffer, buf);
16364
16365
16366 if (prev_buf == buf)
16367 {
16368 if (prev_pt == pt)
16369
16370 return false;
16371
16372 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
16373 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
16374 && composition_valid_p (start, end, prop)
16375 && start < prev_pt && end > prev_pt)
16376
16377
16378 return (pt <= start || pt >= end);
16379 }
16380
16381
16382 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
16383 && find_composition (pt, -1, &start, &end, &prop, buffer)
16384 && composition_valid_p (start, end, prop)
16385 && start < pt && end > pt);
16386 }
16387
16388
16389
16390 static void
16391 reconsider_clip_changes (struct window *w)
16392 {
16393 struct buffer *b = XBUFFER (w->contents);
16394
16395 if (b->clip_changed
16396 && w->window_end_valid
16397 && w->current_matrix->buffer == b
16398 && w->current_matrix->zv == BUF_ZV (b)
16399 && w->current_matrix->begv == BUF_BEGV (b))
16400 b->clip_changed = false;
16401
16402
16403
16404
16405
16406 if (!b->clip_changed && w->window_end_valid)
16407 {
16408 ptrdiff_t pt = (w == XWINDOW (selected_window)
16409 ? PT : marker_position (w->pointm));
16410
16411 if ((w->current_matrix->buffer != b || pt != w->last_point)
16412 && check_point_in_composition (w->current_matrix->buffer,
16413 w->last_point, b, pt))
16414 b->clip_changed = true;
16415 }
16416 }
16417
16418 static void
16419 propagate_buffer_redisplay (void)
16420 {
16421
16422
16423
16424
16425
16426
16427
16428
16429
16430 Lisp_Object ws = window_list ();
16431 for (; CONSP (ws); ws = XCDR (ws))
16432 {
16433 struct window *thisw = XWINDOW (XCAR (ws));
16434 struct buffer *thisb = XBUFFER (thisw->contents);
16435 if (thisb->text->redisplay)
16436 thisw->redisplay = true;
16437 }
16438 }
16439
16440 #define STOP_POLLING \
16441 do { if (! polling_stopped_here) stop_polling (); \
16442 polling_stopped_here = true; } while (false)
16443
16444 #define RESUME_POLLING \
16445 do { if (polling_stopped_here) start_polling (); \
16446 polling_stopped_here = false; } while (false)
16447
16448
16449
16450
16451 static void
16452 redisplay_internal (void)
16453 {
16454 struct window *w = XWINDOW (selected_window);
16455 struct window *sw;
16456 struct frame *fr;
16457 bool pending;
16458 bool must_finish = false, match_p;
16459 struct text_pos tlbufpos, tlendpos;
16460 int number_of_visible_frames;
16461 struct frame *sf;
16462 bool polling_stopped_here = false;
16463 Lisp_Object tail, frame;
16464
16465
16466
16467
16468 enum { MAX_HSCROLL_RETRIES = 16 };
16469 int hscroll_retries = 0;
16470
16471
16472
16473
16474
16475
16476 enum {MAX_GARBAGED_FRAME_RETRIES = 2 };
16477 int garbaged_frame_retries = 0;
16478
16479
16480
16481 bool consider_all_windows_p;
16482
16483
16484 bool update_miniwindow_p = false;
16485
16486 redisplay_trace ("redisplay_internal %d\n", redisplaying_p);
16487
16488
16489
16490
16491 if ((FRAME_INITIAL_P (SELECTED_FRAME ())
16492 && redisplay_skip_initial_frame)
16493 || !NILP (Vinhibit_redisplay))
16494 return;
16495
16496
16497
16498
16499 fr = XFRAME (w->frame);
16500 sf = SELECTED_FRAME ();
16501
16502 if (!fr->glyphs_initialized_p)
16503 return;
16504
16505 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
16506 if (popup_activated ())
16507 return;
16508 #endif
16509
16510 #if defined (HAVE_HAIKU)
16511 if (popup_activated_p)
16512 return;
16513 #endif
16514
16515
16516 if (redisplaying_p)
16517 return;
16518
16519
16520
16521 specpdl_ref count = SPECPDL_INDEX ();
16522 record_unwind_protect_void (unwind_redisplay);
16523 redisplaying_p = true;
16524 block_buffer_flips ();
16525 specbind (Qinhibit_free_realized_faces, Qnil);
16526
16527
16528 record_in_backtrace (Qredisplay_internal_xC_functionx, 0, 0);
16529
16530 FOR_EACH_FRAME (tail, frame)
16531 XFRAME (frame)->already_hscrolled_p = false;
16532
16533 reset_outermost_restrictions ();
16534
16535 retry:
16536
16537 sw = w;
16538
16539 pending = false;
16540 forget_escape_and_glyphless_faces ();
16541
16542 inhibit_free_realized_faces = false;
16543
16544
16545
16546
16547 if (face_change)
16548 windows_or_buffers_changed = 47;
16549
16550 if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
16551 && FRAME_TTY (sf)->previous_frame != sf)
16552 {
16553
16554
16555
16556 SET_FRAME_GARBAGED (sf);
16557 #ifndef DOS_NT
16558 set_tty_color_mode (FRAME_TTY (sf), sf);
16559 #endif
16560 FRAME_TTY (sf)->previous_frame = sf;
16561 }
16562
16563
16564
16565
16566 number_of_visible_frames = 0;
16567
16568 FOR_EACH_FRAME (tail, frame)
16569 {
16570 struct frame *f = XFRAME (frame);
16571
16572 if (FRAME_VISIBLE_P (f))
16573 {
16574 ++number_of_visible_frames;
16575
16576 if (f->fonts_changed)
16577 {
16578 adjust_frame_glyphs (f);
16579
16580
16581
16582
16583
16584
16585 SET_FRAME_GARBAGED (f);
16586 f->fonts_changed = false;
16587 }
16588
16589
16590 if (f != sf && f->cursor_type_changed)
16591 fset_redisplay (f);
16592 }
16593 clear_desired_matrices (f);
16594 }
16595
16596
16597 do_pending_window_change (true);
16598
16599
16600 clear_garbaged_frames ();
16601
16602
16603 if (NILP (Vmemory_full))
16604 prepare_menu_bars ();
16605
16606
16607
16608
16609
16610 if (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)
16611 sw = w;
16612
16613 reconsider_clip_changes (w);
16614
16615
16616 match_p = XBUFFER (w->contents) == current_buffer;
16617 if (match_p)
16618 {
16619
16620 if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
16621 w->update_mode_line = true;
16622
16623 if (mode_line_update_needed (w))
16624 w->update_mode_line = true;
16625
16626
16627
16628
16629 if (current_buffer->clip_changed)
16630 bset_update_mode_line (current_buffer);
16631 }
16632
16633
16634
16635
16636
16637
16638 if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
16639 || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
16640 || (message_cleared_p
16641 && minibuf_level == 0
16642
16643
16644 && !MINI_WINDOW_P (XWINDOW (selected_window))))
16645 {
16646 echo_area_display (false);
16647
16648 if (message_cleared_p)
16649 update_miniwindow_p = true;
16650
16651 must_finish = true;
16652
16653
16654
16655
16656
16657 if (!display_last_displayed_message_p)
16658 message_cleared_p = false;
16659 }
16660 else if (EQ (selected_window, minibuf_window)
16661 && (current_buffer->clip_changed || window_outdated (w))
16662 && resize_mini_window (w, false))
16663 {
16664
16665
16666 must_finish = true;
16667
16668
16669
16670
16671 clear_garbaged_frames ();
16672 }
16673
16674 if (!NILP (Vrun_hooks))
16675 run_window_change_functions ();
16676
16677 if (windows_or_buffers_changed && !update_mode_lines)
16678
16679
16680
16681 update_mode_lines = (windows_or_buffers_changed == REDISPLAY_SOME
16682 ? REDISPLAY_SOME : 32);
16683
16684
16685
16686
16687
16688 overlay_arrows_changed_p (true);
16689
16690 consider_all_windows_p = (update_mode_lines
16691 || windows_or_buffers_changed);
16692
16693 #define AINC(a,i) \
16694 { \
16695 Lisp_Object entry = Fgethash (make_fixnum (i), a, make_fixnum (0)); \
16696 if (FIXNUMP (entry)) \
16697 Fputhash (make_fixnum (i), make_fixnum (1 + XFIXNUM (entry)), a); \
16698 }
16699
16700 AINC (Vredisplay__all_windows_cause, windows_or_buffers_changed);
16701 AINC (Vredisplay__mode_lines_cause, update_mode_lines);
16702
16703
16704
16705
16706
16707 tlbufpos = this_line_start_pos;
16708 tlendpos = this_line_end_pos;
16709 if (!consider_all_windows_p
16710 && CHARPOS (tlbufpos) > 0
16711 && !w->update_mode_line
16712 && !current_buffer->clip_changed
16713 && !current_buffer->prevent_redisplay_optimizations_p
16714 && FRAME_VISIBLE_P (XFRAME (w->frame))
16715 && !FRAME_OBSCURED_P (XFRAME (w->frame))
16716 && !XFRAME (w->frame)->cursor_type_changed
16717 && !XFRAME (w->frame)->face_change
16718
16719 && this_line_buffer == current_buffer
16720 && match_p
16721 && !w->force_start
16722 && !w->optional_new_start
16723
16724 && PT >= CHARPOS (tlbufpos)
16725 && PT <= Z - CHARPOS (tlendpos)
16726
16727
16728
16729
16730
16731
16732 && (NILP (Vdisplay_line_numbers)
16733 || EQ (Vdisplay_line_numbers, Qvisual))
16734
16735
16736 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
16737 CHARPOS (tlendpos)))
16738 {
16739 if (CHARPOS (tlbufpos) > BEGV
16740 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
16741 && (CHARPOS (tlbufpos) == ZV
16742 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
16743
16744 goto cancel;
16745 else if (window_outdated (w) || MINI_WINDOW_P (w))
16746 {
16747
16748
16749
16750
16751
16752
16753
16754
16755
16756
16757
16758
16759
16760
16761
16762 struct it it;
16763 int line_height_before = this_line_pixel_height;
16764
16765
16766
16767 start_display (&it, w, tlbufpos);
16768
16769
16770 if (it.current_x != this_line_start_x)
16771 goto cancel;
16772
16773
16774
16775
16776 if (it.sp > 1
16777 && it.method == GET_FROM_IMAGE && it.image_id == -1)
16778 goto cancel;
16779 redisplay_trace ("trying display optimization 1\n");
16780 w->cursor.vpos = -1;
16781 overlay_arrow_seen = false;
16782 it.vpos = this_line_vpos;
16783 it.current_y = this_line_y;
16784 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
16785 display_line (&it, -1);
16786
16787
16788
16789 if (w->cursor.vpos >= 0
16790
16791
16792 && CHARPOS (this_line_start_pos)
16793
16794 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
16795
16796
16797 && this_line_pixel_height == line_height_before
16798
16799
16800
16801
16802 && !hscrolling_current_line_p (w))
16803 {
16804
16805
16806 if (it.current_y < it.last_visible_y)
16807 {
16808 struct glyph_row *row
16809 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
16810 ptrdiff_t delta, delta_bytes;
16811
16812
16813
16814
16815
16816
16817 delta = (Z
16818 - CHARPOS (tlendpos)
16819 - MATRIX_ROW_START_CHARPOS (row));
16820 delta_bytes = (Z_BYTE
16821 - BYTEPOS (tlendpos)
16822 - MATRIX_ROW_START_BYTEPOS (row));
16823
16824 increment_matrix_positions (w->current_matrix,
16825 this_line_vpos + 1,
16826 w->current_matrix->nrows,
16827 delta, delta_bytes);
16828 }
16829
16830
16831
16832
16833 if (MATRIX_ROW_DISPLAYS_TEXT_P (it.glyph_row - 1))
16834 {
16835 if (w->window_end_vpos < this_line_vpos)
16836 w->window_end_vpos = this_line_vpos;
16837 }
16838 else if (w->window_end_vpos == this_line_vpos
16839 && this_line_vpos > 0)
16840 w->window_end_vpos = this_line_vpos - 1;
16841 w->window_end_valid = false;
16842
16843
16844 w->desired_matrix->no_scrolling_p = true;
16845
16846 #ifdef GLYPH_DEBUG
16847 *w->desired_matrix->method = 0;
16848 debug_method_add (w, "optimization 1");
16849 #endif
16850 #ifdef HAVE_WINDOW_SYSTEM
16851 update_window_fringes (w, false);
16852 #endif
16853 goto update;
16854 }
16855 else
16856 goto cancel;
16857 }
16858 else if (
16859 PT == w->last_point
16860
16861
16862
16863
16864 && 0 <= w->cursor.vpos
16865 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
16866 {
16867 if (!must_finish)
16868 {
16869 do_pending_window_change (true);
16870
16871 if (WINDOWP (selected_window)
16872 && (w = XWINDOW (selected_window)) != sw)
16873 goto retry;
16874
16875
16876
16877 if (w->cursor_off_p == w->last_cursor_off_p)
16878 goto end_of_redisplay;
16879 }
16880 goto update;
16881 }
16882
16883
16884 else if (NILP (Vshow_trailing_whitespace)
16885 && !cursor_in_echo_area
16886 && !composition_break_at_point)
16887 {
16888 struct it it;
16889 struct glyph_row *row;
16890
16891
16892
16893
16894 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
16895 NULL, DEFAULT_FACE_ID);
16896 it.current_x = this_line_start_x;
16897 it.current_y = this_line_y;
16898 it.vpos = this_line_vpos;
16899
16900 if (current_buffer->long_line_optimizations_p
16901 && it.line_wrap == TRUNCATE
16902 && PT - CHARPOS (tlbufpos) > large_hscroll_threshold)
16903 {
16904
16905
16906
16907 reseat_at_next_visible_line_start (&it, false);
16908 if (IT_CHARPOS (it) <= PT)
16909 it.vpos = this_line_vpos + 1;
16910 }
16911 else
16912 {
16913
16914
16915 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
16916 }
16917
16918 if (it.vpos == this_line_vpos
16919 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
16920 row->enabled_p))
16921 {
16922 eassert (this_line_vpos == it.vpos);
16923 eassert (this_line_y == it.current_y);
16924 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
16925 if (cursor_row_fully_visible_p (w, false, true, false))
16926 {
16927 #ifdef GLYPH_DEBUG
16928 *w->desired_matrix->method = 0;
16929 debug_method_add (w, "optimization 3");
16930 #endif
16931 goto update;
16932 }
16933 else
16934 goto cancel;
16935 }
16936 else
16937 goto cancel;
16938 }
16939
16940 cancel:
16941
16942 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, false);
16943 }
16944
16945 CHARPOS (this_line_start_pos) = 0;
16946 ++clear_face_cache_count;
16947 #ifdef HAVE_WINDOW_SYSTEM
16948 ++clear_image_cache_count;
16949 #endif
16950
16951
16952
16953
16954
16955
16956 if (consider_all_windows_p)
16957 {
16958 FOR_EACH_FRAME (tail, frame)
16959 XFRAME (frame)->updated_p = false;
16960
16961 propagate_buffer_redisplay ();
16962
16963 FOR_EACH_FRAME (tail, frame)
16964 {
16965 struct frame *f = XFRAME (frame);
16966
16967
16968
16969 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
16970 && !EQ (FRAME_TTY (f)->top_frame, frame))
16971 continue;
16972
16973 retry_frame:
16974 if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
16975 {
16976 bool gcscrollbars
16977
16978 = f->redisplay || !REDISPLAY_SOME_P ();
16979 bool f_redisplay_flag = f->redisplay;
16980
16981
16982
16983
16984 if (!FRAME_LIVE_P (f))
16985 continue;
16986
16987
16988
16989 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
16990 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
16991
16992 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
16993 {
16994
16995
16996
16997
16998
16999
17000
17001 f->inhibit_clear_image_cache = true;
17002 redisplay_windows (FRAME_ROOT_WINDOW (f));
17003 }
17004
17005
17006 else if (!REDISPLAY_SOME_P ())
17007 f->redisplay = true;
17008
17009
17010 if (!FRAME_LIVE_P (f))
17011 continue;
17012
17013
17014
17015 if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
17016 FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
17017
17018 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
17019 {
17020
17021 if (f->fonts_changed)
17022 {
17023 adjust_frame_glyphs (f);
17024
17025
17026
17027 SET_FRAME_GARBAGED (f);
17028 f->fonts_changed = false;
17029 goto retry_frame;
17030 }
17031
17032
17033 if (!f->already_hscrolled_p)
17034 {
17035 f->already_hscrolled_p = true;
17036 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17037 && hscroll_windows (f->root_window))
17038 {
17039 hscroll_retries++;
17040 goto retry_frame;
17041 }
17042 }
17043
17044
17045
17046
17047
17048
17049
17050
17051
17052
17053
17054
17055 if (!f_redisplay_flag && f->redisplay)
17056 goto retry_frame;
17057
17058
17059
17060
17061
17062
17063
17064
17065
17066 if (FRAME_GARBAGED_P (f)
17067 && garbaged_frame_retries++ < MAX_GARBAGED_FRAME_RETRIES)
17068 goto retry;
17069
17070 #ifdef HAVE_WINDOW_SYSTEM
17071 if (FRAME_WINDOW_P (f)
17072 && FRAME_RIF (f)->clear_under_internal_border)
17073 FRAME_RIF (f)->clear_under_internal_border (f);
17074 #endif
17075
17076
17077
17078 if (interrupt_input)
17079 unrequest_sigio ();
17080 STOP_POLLING;
17081
17082 pending |= update_frame (f, false, false);
17083
17084
17085
17086
17087
17088
17089
17090 if (FRAME_GARBAGED_P (f))
17091 {
17092 fset_redisplay (f);
17093 f->garbaged = false;
17094 goto retry_frame;
17095 }
17096 f->cursor_type_changed = false;
17097 f->updated_p = true;
17098 f->inhibit_clear_image_cache = false;
17099 }
17100 }
17101 }
17102
17103 eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
17104
17105 if (!pending)
17106 {
17107
17108
17109
17110 FOR_EACH_FRAME (tail, frame)
17111 {
17112 struct frame *f = XFRAME (frame);
17113 if (f->updated_p)
17114 {
17115 f->redisplay = false;
17116 f->garbaged = false;
17117 mark_window_display_accurate (f->root_window, true);
17118 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
17119 FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
17120 }
17121 }
17122 }
17123 }
17124 else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
17125 {
17126 sf->inhibit_clear_image_cache = true;
17127 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
17128
17129
17130 internal_condition_case_1 (redisplay_window_1, selected_window,
17131 list_of_error,
17132 redisplay_window_error);
17133 if (update_miniwindow_p)
17134 {
17135 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17136
17137 displayed_buffer = XBUFFER (XWINDOW (mini_window)->contents);
17138 internal_condition_case_1 (redisplay_window_1, mini_window,
17139 list_of_error,
17140 redisplay_window_error);
17141 }
17142
17143
17144
17145 update:
17146
17147
17148
17149 if (sf->fonts_changed || sf->redisplay)
17150 {
17151 if (sf->redisplay)
17152 {
17153
17154
17155
17156
17157
17158
17159 windows_or_buffers_changed = 50;
17160 }
17161 goto retry;
17162 }
17163
17164
17165
17166 inhibit_free_realized_faces = true;
17167
17168
17169
17170
17171 if (interrupt_input)
17172 unrequest_sigio ();
17173 STOP_POLLING;
17174
17175 if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
17176 {
17177 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17178 && hscroll_windows (selected_window))
17179 {
17180 hscroll_retries++;
17181 goto retry;
17182 }
17183
17184 XWINDOW (selected_window)->must_be_updated_p = true;
17185 pending = update_frame (sf, false, false);
17186 sf->cursor_type_changed = false;
17187 sf->inhibit_clear_image_cache = false;
17188 }
17189
17190
17191
17192
17193
17194
17195 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17196 struct frame *mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
17197
17198 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
17199 {
17200 XWINDOW (mini_window)->must_be_updated_p = true;
17201 pending |= update_frame (mini_frame, false, false);
17202 mini_frame->cursor_type_changed = false;
17203 if (!pending && hscroll_retries <= MAX_HSCROLL_RETRIES
17204 && hscroll_windows (mini_window))
17205 {
17206 hscroll_retries++;
17207 goto retry;
17208 }
17209 }
17210 }
17211
17212
17213
17214 if (pending)
17215 {
17216
17217
17218
17219 CHARPOS (this_line_start_pos) = 0;
17220
17221
17222 update_overlay_arrows (0);
17223
17224
17225
17226 if (!WINDOW_FULL_WIDTH_P (w)
17227 && !FRAME_WINDOW_P (XFRAME (w->frame)))
17228 update_mode_lines = 36;
17229 }
17230 else
17231 {
17232 if (!consider_all_windows_p)
17233 {
17234
17235
17236 if (XBUFFER (w->contents)->text->redisplay
17237 && buffer_window_count (XBUFFER (w->contents)) > 1)
17238
17239
17240 propagate_buffer_redisplay ();
17241 mark_window_display_accurate_1 (w, true);
17242
17243
17244 update_overlay_arrows (1);
17245
17246 if (FRAME_TERMINAL (sf)->frame_up_to_date_hook != 0)
17247 FRAME_TERMINAL (sf)->frame_up_to_date_hook (sf);
17248 }
17249
17250 update_mode_lines = 0;
17251 windows_or_buffers_changed = 0;
17252 }
17253
17254
17255
17256
17257
17258 if (interrupt_input)
17259 request_sigio ();
17260 RESUME_POLLING;
17261
17262
17263
17264
17265
17266
17267
17268 if (!pending)
17269 {
17270 int new_count = 0;
17271
17272 FOR_EACH_FRAME (tail, frame)
17273 {
17274 if (XFRAME (frame)->visible)
17275 new_count++;
17276 }
17277
17278 if (new_count != number_of_visible_frames)
17279 windows_or_buffers_changed = 52;
17280 }
17281
17282
17283 do_pending_window_change (true);
17284
17285
17286
17287 if ((windows_or_buffers_changed && !pending)
17288 || (WINDOWP (selected_window)
17289 && (w = XWINDOW (selected_window)) != sw))
17290 goto retry;
17291
17292
17293
17294
17295
17296
17297
17298 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
17299 {
17300 clear_face_cache (false);
17301 clear_face_cache_count = 0;
17302 }
17303
17304 #ifdef HAVE_WINDOW_SYSTEM
17305 if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
17306 {
17307 clear_image_caches (Qnil);
17308 clear_image_cache_count = 0;
17309 }
17310 #endif
17311
17312 end_of_redisplay:
17313 #ifdef HAVE_NS
17314 ns_set_doc_edited ();
17315 #endif
17316 if (interrupt_input && interrupts_deferred)
17317 request_sigio ();
17318
17319
17320
17321 if (max_redisplay_ticks > 0)
17322 update_redisplay_ticks (0, NULL);
17323
17324 unbind_to (count, Qnil);
17325 RESUME_POLLING;
17326 }
17327
17328 static void
17329 unwind_redisplay_preserve_echo_area (void)
17330 {
17331 unblock_buffer_flips ();
17332 }
17333
17334
17335
17336
17337
17338
17339
17340
17341
17342
17343
17344
17345 void
17346 redisplay_preserve_echo_area (int from_where)
17347 {
17348 redisplay_trace ("redisplay_preserve_echo_area (%d)\n", from_where);
17349
17350 block_input ();
17351 specpdl_ref count = SPECPDL_INDEX ();
17352 record_unwind_protect_void (unwind_redisplay_preserve_echo_area);
17353 block_buffer_flips ();
17354 unblock_input ();
17355
17356 if (!NILP (echo_area_buffer[1]))
17357 {
17358
17359
17360 display_last_displayed_message_p = true;
17361 redisplay_internal ();
17362 display_last_displayed_message_p = false;
17363 }
17364 else
17365 redisplay_internal ();
17366
17367 flush_frame (SELECTED_FRAME ());
17368 unbind_to (count, Qnil);
17369 }
17370
17371
17372
17373
17374 static void
17375 unwind_redisplay (void)
17376 {
17377 redisplaying_p = false;
17378 unblock_buffer_flips ();
17379 }
17380
17381
17382
17383 void
17384 unwind_display_working_on_window (void)
17385 {
17386 display_working_on_window_p = false;
17387 }
17388
17389
17390
17391
17392
17393
17394 static void
17395 mark_window_display_accurate_1 (struct window *w, bool accurate_p)
17396 {
17397 struct buffer *b = XBUFFER (w->contents);
17398
17399 w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
17400 w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
17401 w->last_had_star = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
17402
17403 if (accurate_p)
17404 {
17405 b->clip_changed = false;
17406 b->prevent_redisplay_optimizations_p = false;
17407 eassert (buffer_window_count (b) > 0);
17408
17409
17410
17411 b->text->redisplay = false;
17412
17413 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
17414 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
17415 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
17416 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
17417
17418 w->current_matrix->buffer = b;
17419 w->current_matrix->begv = BUF_BEGV (b);
17420 w->current_matrix->zv = BUF_ZV (b);
17421 w->current_matrix->header_line_p = window_wants_header_line (w);
17422 w->current_matrix->tab_line_p = window_wants_tab_line (w);
17423
17424 w->last_cursor_vpos = w->cursor.vpos;
17425 w->last_cursor_off_p = w->cursor_off_p;
17426
17427 if (w == XWINDOW (selected_window))
17428 w->last_point = BUF_PT (b);
17429 else
17430 w->last_point = marker_position (w->pointm);
17431
17432 w->window_end_valid = true;
17433 w->update_mode_line = false;
17434 w->preserve_vscroll_p = false;
17435 }
17436
17437 w->redisplay = !accurate_p;
17438 }
17439
17440
17441
17442
17443
17444
17445
17446 void
17447 mark_window_display_accurate (Lisp_Object window, bool accurate_p)
17448 {
17449 struct window *w;
17450
17451 for (; !NILP (window); window = w->next)
17452 {
17453 w = XWINDOW (window);
17454 if (WINDOWP (w->contents))
17455 mark_window_display_accurate (w->contents, accurate_p);
17456 else
17457 mark_window_display_accurate_1 (w, accurate_p);
17458 }
17459
17460 if (accurate_p)
17461 update_overlay_arrows (1);
17462 else
17463
17464
17465
17466 update_overlay_arrows (-1);
17467 }
17468
17469
17470
17471
17472
17473
17474
17475 Lisp_Object
17476 disp_char_vector (struct Lisp_Char_Table *dp, int c)
17477 {
17478 Lisp_Object val;
17479
17480 if (ASCII_CHAR_P (c))
17481 {
17482 val = dp->ascii;
17483 if (SUB_CHAR_TABLE_P (val))
17484 val = XSUB_CHAR_TABLE (val)->contents[c];
17485 }
17486 else
17487 {
17488 Lisp_Object table;
17489
17490 XSETCHAR_TABLE (table, dp);
17491 val = char_table_ref (table, c);
17492 }
17493 if (NILP (val))
17494 val = dp->defalt;
17495 return val;
17496 }
17497
17498 static int buffer_flip_blocked_depth;
17499
17500 static void
17501 block_buffer_flips (void)
17502 {
17503 eassert (buffer_flip_blocked_depth >= 0);
17504 buffer_flip_blocked_depth++;
17505 }
17506
17507 static void
17508 unblock_buffer_flips (void)
17509 {
17510 eassert (buffer_flip_blocked_depth > 0);
17511 if (--buffer_flip_blocked_depth == 0)
17512 {
17513 Lisp_Object tail, frame;
17514 block_input ();
17515 FOR_EACH_FRAME (tail, frame)
17516 {
17517 struct frame *f = XFRAME (frame);
17518 if (FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook)
17519 (*FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook) (f);
17520 }
17521 unblock_input ();
17522 }
17523 }
17524
17525 bool
17526 buffer_flipping_blocked_p (void)
17527 {
17528 return buffer_flip_blocked_depth > 0;
17529 }
17530
17531
17532
17533
17534
17535
17536
17537
17538 static void
17539 redisplay_windows (Lisp_Object window)
17540 {
17541 while (!NILP (window))
17542 {
17543 struct window *w = XWINDOW (window);
17544
17545 if (WINDOWP (w->contents))
17546 redisplay_windows (w->contents);
17547 else if (BUFFERP (w->contents))
17548 {
17549 displayed_buffer = XBUFFER (w->contents);
17550
17551
17552 internal_condition_case_1 (redisplay_window_0, window,
17553 list_of_error,
17554 redisplay_window_error);
17555 }
17556
17557 window = w->next;
17558 }
17559 }
17560
17561 static Lisp_Object
17562 redisplay_window_error (Lisp_Object error_data)
17563 {
17564 displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
17565
17566
17567
17568 if (max_redisplay_ticks > 0
17569 && CONSP (error_data)
17570 && EQ (XCAR (error_data), Qerror)
17571 && STRINGP (XCAR (XCDR (error_data))))
17572 Vdelayed_warnings_list = Fcons (list2 (XCAR (error_data),
17573 XCAR (XCDR (error_data))),
17574 Vdelayed_warnings_list);
17575 return Qnil;
17576 }
17577
17578 static Lisp_Object
17579 redisplay_window_0 (Lisp_Object window)
17580 {
17581 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17582 redisplay_window (window, false);
17583 return Qnil;
17584 }
17585
17586 static Lisp_Object
17587 redisplay_window_1 (Lisp_Object window)
17588 {
17589 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17590 redisplay_window (window, true);
17591 return Qnil;
17592 }
17593
17594
17595
17596
17597
17598
17599
17600
17601
17602
17603
17604
17605
17606
17607
17608
17609
17610
17611
17612 void
17613 update_redisplay_ticks (int ticks, struct window *w)
17614 {
17615
17616 static struct window *cwindow;
17617 static EMACS_INT window_ticks;
17618
17619
17620
17621
17622 if (!ticks && w != cwindow)
17623 {
17624 cwindow = w;
17625 window_ticks = 0;
17626 }
17627
17628
17629 if ((!w && !redisplaying_p && !display_working_on_window_p)
17630
17631
17632 || (w && MINI_WINDOW_P (w)))
17633 return;
17634
17635 if (ticks > 0)
17636 window_ticks += ticks;
17637 if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks)
17638 {
17639
17640
17641
17642 Lisp_Object contents = w ? w->contents : Qnil;
17643 char *bufname =
17644 NILP (contents)
17645 ? SSDATA (BVAR (current_buffer, name))
17646 : (BUFFERP (contents)
17647 ? SSDATA (BVAR (XBUFFER (contents), name))
17648 : (char *) "<unknown>");
17649
17650 windows_or_buffers_changed = 177;
17651
17652
17653
17654 if (w && w->desired_matrix)
17655 w->desired_matrix->no_scrolling_p = true;
17656 error ("Window showing buffer %s takes too long to redisplay", bufname);
17657 }
17658 }
17659
17660
17661
17662
17663
17664
17665
17666
17667
17668
17669 static bool
17670 set_cursor_from_row (struct window *w, struct glyph_row *row,
17671 struct glyph_matrix *matrix,
17672 ptrdiff_t delta, ptrdiff_t delta_bytes,
17673 int dy, int dvpos)
17674 {
17675 struct glyph *glyph = row->glyphs[TEXT_AREA];
17676 struct glyph *end = glyph + row->used[TEXT_AREA];
17677 struct glyph *cursor = NULL;
17678
17679 ptrdiff_t last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
17680 int x = row->x;
17681 ptrdiff_t pt_old = PT - delta;
17682 ptrdiff_t pos_before = MATRIX_ROW_START_CHARPOS (row) + delta;
17683 ptrdiff_t pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
17684 struct glyph *glyph_before = glyph - 1, *glyph_after = end;
17685
17686
17687 struct glyph *glyphs_end = end;
17688
17689
17690 bool match_with_avoid_cursor = false;
17691
17692
17693 bool string_seen = false;
17694
17695
17696 ptrdiff_t bpos_max = pos_before;
17697 ptrdiff_t bpos_min = pos_after;
17698
17699
17700 ptrdiff_t bpos_covered = 0;
17701
17702
17703 bool string_from_text_prop = false;
17704
17705
17706
17707
17708 eassert (!row->mode_line_p);
17709 if (row->mode_line_p)
17710 return false;
17711
17712
17713
17714
17715 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
17716 {
17717 if (!row->reversed_p)
17718 {
17719 while (glyph < end
17720 && NILP (glyph->object)
17721 && glyph->charpos < 0)
17722 {
17723 x += glyph->pixel_width;
17724 ++glyph;
17725 }
17726 while (end > glyph
17727 && NILP ((end - 1)->object)
17728
17729
17730 && (end - 1)->charpos <= 0)
17731 --end;
17732 glyph_before = glyph - 1;
17733 glyph_after = end;
17734 }
17735 else
17736 {
17737 struct glyph *g;
17738
17739
17740
17741 glyphs_end = end = glyph - 1;
17742 glyph += row->used[TEXT_AREA] - 1;
17743
17744 while (glyph > end + 1
17745 && NILP (glyph->object)
17746 && glyph->charpos < 0)
17747 --glyph;
17748 if (NILP (glyph->object) && glyph->charpos < 0)
17749 --glyph;
17750
17751
17752 for (x = 0, g = end + 1; g < glyph; g++)
17753 x += g->pixel_width;
17754 while (end < glyph
17755 && NILP ((end + 1)->object)
17756 && (end + 1)->charpos <= 0)
17757 ++end;
17758 glyph_before = glyph + 1;
17759 glyph_after = end;
17760 }
17761 }
17762 else if (row->reversed_p)
17763 {
17764
17765
17766
17767 cursor = end - 1;
17768
17769
17770
17771 if (!FRAME_WINDOW_P (WINDOW_XFRAME (w))
17772 && !WINDOW_RIGHTMOST_P (w)
17773 && cursor == row->glyphs[LAST_AREA] - 1)
17774 cursor--;
17775 x = -1;
17776 }
17777
17778
17779
17780
17781
17782 if (!row->reversed_p)
17783 while (
17784 glyph < end
17785
17786 && !NILP (glyph->object))
17787 {
17788 if (BUFFERP (glyph->object))
17789 {
17790 ptrdiff_t dpos = glyph->charpos - pt_old;
17791
17792 if (glyph->charpos > bpos_max)
17793 bpos_max = glyph->charpos;
17794 if (glyph->charpos < bpos_min)
17795 bpos_min = glyph->charpos;
17796 if (!glyph->avoid_cursor_p)
17797 {
17798
17799
17800 if (dpos == 0)
17801 {
17802 match_with_avoid_cursor = false;
17803 break;
17804 }
17805
17806
17807 if (0 > dpos && dpos > pos_before - pt_old)
17808 {
17809 pos_before = glyph->charpos;
17810 glyph_before = glyph;
17811 }
17812 else if (0 < dpos && dpos < pos_after - pt_old)
17813 {
17814 pos_after = glyph->charpos;
17815 glyph_after = glyph;
17816 }
17817 }
17818 else if (dpos == 0)
17819 match_with_avoid_cursor = true;
17820 }
17821 else if (STRINGP (glyph->object))
17822 {
17823 Lisp_Object chprop;
17824 ptrdiff_t glyph_pos = glyph->charpos;
17825
17826 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
17827 glyph->object);
17828 if (!NILP (chprop))
17829 {
17830
17831
17832
17833
17834
17835
17836
17837
17838
17839
17840 ptrdiff_t prop_pos =
17841 string_buffer_position_lim (glyph->object, pos_before,
17842 pos_after, false);
17843
17844 if (prop_pos >= pos_before)
17845 bpos_max = prop_pos;
17846 }
17847 if (FIXNUMP (chprop))
17848 {
17849 bpos_covered = bpos_max + XFIXNUM (chprop);
17850
17851
17852
17853
17854
17855
17856
17857
17858
17859
17860
17861 if (bpos_max <= pt_old && bpos_covered >= pt_old)
17862 {
17863 cursor = glyph;
17864 break;
17865 }
17866 }
17867
17868 string_seen = true;
17869 }
17870 x += glyph->pixel_width;
17871 ++glyph;
17872 }
17873 else if (glyph > end)
17874 while (!NILP (glyph->object))
17875 {
17876 if (BUFFERP (glyph->object))
17877 {
17878 ptrdiff_t dpos = glyph->charpos - pt_old;
17879
17880 if (glyph->charpos > bpos_max)
17881 bpos_max = glyph->charpos;
17882 if (glyph->charpos < bpos_min)
17883 bpos_min = glyph->charpos;
17884 if (!glyph->avoid_cursor_p)
17885 {
17886 if (dpos == 0)
17887 {
17888 match_with_avoid_cursor = false;
17889 break;
17890 }
17891 if (0 > dpos && dpos > pos_before - pt_old)
17892 {
17893 pos_before = glyph->charpos;
17894 glyph_before = glyph;
17895 }
17896 else if (0 < dpos && dpos < pos_after - pt_old)
17897 {
17898 pos_after = glyph->charpos;
17899 glyph_after = glyph;
17900 }
17901 }
17902 else if (dpos == 0)
17903 match_with_avoid_cursor = true;
17904 }
17905 else if (STRINGP (glyph->object))
17906 {
17907 Lisp_Object chprop;
17908 ptrdiff_t glyph_pos = glyph->charpos;
17909
17910 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
17911 glyph->object);
17912 if (!NILP (chprop))
17913 {
17914 ptrdiff_t prop_pos =
17915 string_buffer_position_lim (glyph->object, pos_before,
17916 pos_after, false);
17917
17918 if (prop_pos >= pos_before)
17919 bpos_max = prop_pos;
17920 }
17921 if (FIXNUMP (chprop))
17922 {
17923 bpos_covered = bpos_max + XFIXNUM (chprop);
17924
17925
17926
17927 if (bpos_max <= pt_old && bpos_covered >= pt_old)
17928 {
17929 cursor = glyph;
17930 break;
17931 }
17932 }
17933 string_seen = true;
17934 }
17935 --glyph;
17936 if (glyph == glyphs_end)
17937 {
17938 x--;
17939 break;
17940 }
17941 x -= glyph->pixel_width;
17942 }
17943
17944
17945
17946
17947 if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
17948 && BUFFERP (glyph->object) && glyph->charpos == pt_old)
17949 && !(bpos_max <= pt_old && pt_old <= bpos_covered))
17950 {
17951
17952
17953
17954
17955
17956 bool empty_line_p =
17957 ((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
17958 && NILP (glyph->object) && glyph->charpos > 0
17959
17960
17961
17962
17963 && !(row->continued_p || row->truncated_on_right_p));
17964
17965 if (row->ends_in_ellipsis_p && pos_after == last_pos)
17966 {
17967 ptrdiff_t ellipsis_pos;
17968
17969
17970 if (!row->reversed_p)
17971 {
17972 ellipsis_pos = (glyph - 1)->charpos;
17973 while (glyph > row->glyphs[TEXT_AREA]
17974 && (glyph - 1)->charpos == ellipsis_pos)
17975 glyph--, x -= glyph->pixel_width;
17976
17977
17978
17979 x += glyph->pixel_width;
17980 glyph++;
17981 }
17982 else
17983 {
17984 ellipsis_pos = (glyph + 1)->charpos;
17985 while (glyph < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
17986 && (glyph + 1)->charpos == ellipsis_pos)
17987 glyph++, x += glyph->pixel_width;
17988 x -= glyph->pixel_width;
17989 glyph--;
17990 }
17991 }
17992 else if (match_with_avoid_cursor)
17993 {
17994 cursor = glyph_after;
17995 x = -1;
17996 }
17997 else if (string_seen)
17998 {
17999 int incr = row->reversed_p ? -1 : +1;
18000
18001
18002
18003
18004
18005
18006 struct glyph *start, *stop;
18007 ptrdiff_t pos = pos_before;
18008
18009 x = -1;
18010
18011
18012
18013
18014
18015
18016 if (row->ends_in_newline_from_string_p)
18017 {
18018 glyph_after = end;
18019 pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
18020 }
18021
18022
18023
18024
18025
18026
18027
18028
18029
18030 if (!row->reversed_p)
18031 {
18032 start = min (glyph_before, glyph_after);
18033 stop = max (glyph_before, glyph_after);
18034 }
18035 else
18036 {
18037 start = max (glyph_before, glyph_after);
18038 stop = min (glyph_before, glyph_after);
18039 }
18040 for (glyph = start + incr;
18041 row->reversed_p ? glyph > stop : glyph < stop; )
18042 {
18043
18044
18045
18046
18047 if (STRINGP (glyph->object))
18048 {
18049 Lisp_Object str;
18050 ptrdiff_t tem;
18051
18052
18053 ptrdiff_t lim = pos_after
18054 + (pos_after == MATRIX_ROW_END_CHARPOS (row) + delta);
18055
18056 string_from_text_prop = false;
18057 str = glyph->object;
18058 tem = string_buffer_position_lim (str, pos, lim, false);
18059 if (tem == 0
18060 || pos <= tem)
18061 {
18062
18063
18064
18065
18066
18067
18068
18069
18070
18071
18072 if (tem == 0
18073 || tem == pt_old
18074 || (tem - pt_old > 0 && tem < pos_after))
18075 {
18076
18077
18078
18079
18080
18081
18082 ptrdiff_t strpos = glyph->charpos;
18083
18084 if (tem)
18085 {
18086 cursor = glyph;
18087 string_from_text_prop = true;
18088 }
18089 for ( ;
18090 (row->reversed_p ? glyph > stop : glyph < stop)
18091 && EQ (glyph->object, str);
18092 glyph += incr)
18093 {
18094 Lisp_Object cprop;
18095 ptrdiff_t gpos = glyph->charpos;
18096
18097 cprop = Fget_char_property (make_fixnum (gpos),
18098 Qcursor,
18099 glyph->object);
18100 if (!NILP (cprop))
18101 {
18102 cursor = glyph;
18103 break;
18104 }
18105 if (tem && glyph->charpos < strpos)
18106 {
18107 strpos = glyph->charpos;
18108 cursor = glyph;
18109 }
18110 }
18111
18112 if (tem == pt_old
18113 || (tem - pt_old > 0 && tem < pos_after))
18114 goto compute_x;
18115 }
18116 if (tem)
18117 pos = tem + 1;
18118 }
18119
18120
18121 while ((row->reversed_p ? glyph > stop : glyph < stop)
18122 && EQ (glyph->object, str))
18123 glyph += incr;
18124 }
18125 else
18126 glyph += incr;
18127 }
18128
18129
18130
18131 if (cursor == NULL
18132 && (row->reversed_p ? glyph <= end : glyph >= end)
18133 && (row->reversed_p ? end > glyphs_end : end < glyphs_end)
18134 && STRINGP (end->object)
18135 && row->continued_p)
18136 return false;
18137 }
18138
18139
18140
18141
18142
18143 else if (row->truncated_on_left_p && pt_old < bpos_min)
18144 {
18145 cursor = glyph_before;
18146 x = -1;
18147 }
18148 else if ((row->truncated_on_right_p && pt_old > bpos_max)
18149
18150 || (!empty_line_p
18151 && (row->reversed_p
18152 ? glyph_after > glyphs_end
18153 : glyph_after < glyphs_end)))
18154 {
18155 cursor = glyph_after;
18156 x = -1;
18157 }
18158 }
18159
18160 compute_x:
18161 if (cursor != NULL)
18162 glyph = cursor;
18163 else if (glyph == glyphs_end
18164 && pos_before == pos_after
18165 && STRINGP ((row->reversed_p
18166 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18167 : row->glyphs[TEXT_AREA])->object))
18168 {
18169
18170
18171
18172
18173 glyph =
18174 row->reversed_p
18175 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18176 : row->glyphs[TEXT_AREA];
18177 }
18178 if (x < 0)
18179 {
18180 struct glyph *g;
18181
18182
18183 for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
18184 {
18185 if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
18186 emacs_abort ();
18187 x += g->pixel_width;
18188 }
18189 }
18190
18191
18192
18193
18194
18195
18196 if (
18197 w->cursor.vpos >= 0
18198
18199 && MATRIX_ROW (matrix, w->cursor.vpos) != row
18200
18201
18202
18203
18204
18205 && MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos)) <= pt_old
18206 && pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18207 && cursor_row_p (MATRIX_ROW (matrix, w->cursor.vpos)))
18208 {
18209 struct glyph *g1
18210 = MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
18211
18212
18213 if (!(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end))
18214 return false;
18215
18216
18217 if (
18218 w->cursor.hpos >= 0
18219 && w->cursor.hpos < MATRIX_ROW_USED (matrix, w->cursor.vpos)
18220 && ((BUFFERP (g1->object)
18221 && (g1->charpos == pt_old
18222 || (BUFFERP (glyph->object)
18223 && eabs (g1->charpos - pt_old)
18224 < eabs (glyph->charpos - pt_old))))
18225
18226
18227 || (STRINGP (g1->object)
18228 && (!NILP (Fget_char_property (make_fixnum (g1->charpos),
18229 Qcursor, g1->object))
18230
18231
18232
18233 || (EQ (g1->object, glyph->object)
18234 && string_from_text_prop)
18235
18236
18237 || (NILP (glyph->object)
18238 && glyph->charpos != pt_old)))))
18239 return false;
18240
18241 if (!((BUFFERP (glyph->object) && glyph->charpos == pt_old)
18242
18243
18244
18245 || (!row->continued_p
18246 && NILP (glyph->object)
18247 && glyph->charpos == 0
18248 && pt_old == MATRIX_ROW_END_CHARPOS (row) - 1))
18249
18250
18251
18252
18253
18254 && MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18255 - MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18256 < MATRIX_ROW_END_CHARPOS (row) - MATRIX_ROW_START_CHARPOS (row))
18257 return false;
18258 }
18259 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
18260 w->cursor.x = x;
18261 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
18262 w->cursor.y = row->y + dy;
18263
18264 if (w == XWINDOW (selected_window))
18265 {
18266 if (!row->continued_p
18267 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
18268 && row->x == 0)
18269 {
18270 this_line_buffer = XBUFFER (w->contents);
18271
18272 CHARPOS (this_line_start_pos)
18273 = MATRIX_ROW_START_CHARPOS (row) + delta;
18274 BYTEPOS (this_line_start_pos)
18275 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
18276
18277 CHARPOS (this_line_end_pos)
18278 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
18279 BYTEPOS (this_line_end_pos)
18280 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
18281
18282 this_line_y = w->cursor.y;
18283 this_line_pixel_height = row->height;
18284 this_line_vpos = w->cursor.vpos;
18285 this_line_start_x = row->x;
18286 }
18287 else
18288 CHARPOS (this_line_start_pos) = 0;
18289 }
18290
18291 return true;
18292 }
18293
18294
18295
18296
18297
18298
18299
18300 static struct text_pos
18301 run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
18302 {
18303 struct window *w = XWINDOW (window);
18304 SET_MARKER_FROM_TEXT_POS (w->start, startp);
18305
18306 eassert (current_buffer == XBUFFER (w->contents));
18307
18308 if (!NILP (Vwindow_scroll_functions))
18309 {
18310 specpdl_ref count = SPECPDL_INDEX ();
18311 specbind (Qinhibit_quit, Qt);
18312 safe_run_hooks_2
18313 (Qwindow_scroll_functions, window, make_fixnum (CHARPOS (startp)));
18314 unbind_to (count, Qnil);
18315 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18316
18317 set_buffer_internal (XBUFFER (w->contents));
18318 }
18319
18320 return startp;
18321 }
18322
18323
18324
18325
18326
18327
18328
18329
18330
18331
18332
18333
18334
18335
18336
18337
18338
18339
18340
18341
18342
18343
18344 static bool
18345 cursor_row_fully_visible_p (struct window *w, bool force_p,
18346 bool current_matrix_p,
18347 bool just_test_user_preference_p)
18348 {
18349 struct glyph_matrix *matrix;
18350 struct glyph_row *row;
18351 int window_height;
18352 Lisp_Object mclfv_p =
18353 buffer_local_value (Qmake_cursor_line_fully_visible, w->contents);
18354
18355
18356 if (BASE_EQ (mclfv_p, Qunbound))
18357 mclfv_p = Vmake_cursor_line_fully_visible;
18358
18359
18360 if (FUNCTIONP (mclfv_p))
18361 {
18362 Lisp_Object window;
18363 XSETWINDOW (window, w);
18364
18365
18366 Lisp_Object val = safe_call1 (mclfv_p, window);
18367 if (NILP (val))
18368 return true;
18369 else if (just_test_user_preference_p)
18370 return false;
18371 }
18372 else if (NILP (mclfv_p))
18373 return true;
18374 else if (just_test_user_preference_p)
18375 return false;
18376
18377
18378
18379 if (w->cursor.vpos < 0)
18380 return true;
18381
18382 matrix = current_matrix_p ? w->current_matrix : w->desired_matrix;
18383 row = MATRIX_ROW (matrix, w->cursor.vpos);
18384
18385
18386 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row))
18387 return true;
18388
18389
18390
18391 window_height = window_box_height (w);
18392 if (row->height >= window_height)
18393 {
18394 if (!force_p || MINI_WINDOW_P (w)
18395 || w->vscroll || w->cursor.vpos == 0)
18396 return true;
18397 }
18398 return false;
18399 }
18400
18401
18402
18403
18404
18405
18406
18407
18408
18409
18410
18411
18412
18413
18414
18415
18416
18417
18418
18419
18420 enum
18421 {
18422 SCROLLING_SUCCESS = 1,
18423 SCROLLING_FAILED = 0,
18424 SCROLLING_NEED_LARGER_MATRICES = -1
18425 };
18426
18427
18428
18429
18430
18431 #define SCROLL_LIMIT 100
18432
18433 static int
18434 try_scrolling (Lisp_Object window, bool just_this_one_p,
18435 intmax_t arg_scroll_conservatively, intmax_t scroll_step,
18436 bool temp_scroll_step, bool last_line_misfit)
18437 {
18438 struct window *w = XWINDOW (window);
18439 struct text_pos pos, startp;
18440 struct it it;
18441 int this_scroll_margin, scroll_max, rc, height;
18442 int dy = 0, amount_to_scroll = 0;
18443 bool scroll_down_p = false;
18444 int extra_scroll_margin_lines = last_line_misfit;
18445 Lisp_Object aggressive;
18446
18447 int scroll_limit = SCROLL_LIMIT;
18448 int frame_line_height = default_line_pixel_height (w);
18449
18450 #ifdef GLYPH_DEBUG
18451 debug_method_add (w, "try_scrolling");
18452 #endif
18453
18454 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18455
18456 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18457
18458
18459
18460
18461
18462 if (arg_scroll_conservatively > scroll_limit)
18463 {
18464 arg_scroll_conservatively = scroll_limit + 1;
18465 scroll_max = scroll_limit * frame_line_height;
18466 }
18467 else if (0 < scroll_step || 0 < arg_scroll_conservatively || temp_scroll_step)
18468
18469
18470 {
18471 intmax_t scroll_lines_max
18472 = max (scroll_step, max (arg_scroll_conservatively, temp_scroll_step));
18473 int scroll_lines = clip_to_bounds (0, scroll_lines_max, 1000000);
18474 scroll_max = scroll_lines * frame_line_height;
18475 }
18476 else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
18477 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
18478
18479
18480 scroll_max = 10 * frame_line_height;
18481 else
18482 scroll_max = 0;
18483
18484 too_near_end:
18485
18486
18487 if (PT > CHARPOS (startp))
18488 {
18489 int scroll_margin_y;
18490
18491
18492
18493 start_display (&it, w, startp);
18494 scroll_margin_y = it.last_visible_y - partial_line_height (&it)
18495 - this_scroll_margin
18496 - frame_line_height * extra_scroll_margin_lines;
18497 move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
18498 (MOVE_TO_POS | MOVE_TO_Y));
18499
18500 if (PT > CHARPOS (it.current.pos))
18501 {
18502 int y0 = line_bottom_y (&it);
18503
18504
18505
18506
18507
18508 int slack = max (scroll_max, 10 * frame_line_height);
18509 int y_to_move = it.last_visible_y + slack;
18510
18511
18512
18513
18514
18515 move_it_to (&it, PT, -1, y_to_move,
18516 -1, MOVE_TO_POS | MOVE_TO_Y);
18517 dy = line_bottom_y (&it) - y0;
18518
18519 if (dy > scroll_max)
18520 return SCROLLING_FAILED;
18521
18522 if (dy > 0)
18523 scroll_down_p = true;
18524 }
18525 else if (PT == IT_CHARPOS (it)
18526 && IT_CHARPOS (it) < ZV
18527 && it.method == GET_FROM_STRING
18528 && arg_scroll_conservatively > scroll_limit
18529 && it.current_x == 0)
18530 {
18531 enum move_it_result skip;
18532 int y1 = it.current_y;
18533 int vpos;
18534
18535
18536
18537
18538
18539
18540
18541 do {
18542 skip = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
18543 if (skip != MOVE_NEWLINE_OR_CR
18544 || IT_CHARPOS (it) != PT
18545 || it.method == GET_FROM_BUFFER)
18546 break;
18547 vpos = it.vpos;
18548 move_it_to (&it, -1, -1, -1, vpos + 1, MOVE_TO_VPOS);
18549 } while (it.vpos > vpos);
18550
18551 dy = it.current_y - y1;
18552
18553 if (dy > scroll_max)
18554 return SCROLLING_FAILED;
18555
18556 if (dy > 0)
18557 scroll_down_p = true;
18558 }
18559 }
18560
18561 if (scroll_down_p)
18562 {
18563
18564
18565
18566
18567 if (arg_scroll_conservatively)
18568 amount_to_scroll
18569 = min (max (dy, frame_line_height),
18570 frame_line_height * arg_scroll_conservatively);
18571 else if (scroll_step || temp_scroll_step)
18572 amount_to_scroll = scroll_max;
18573 else
18574 {
18575 aggressive = BVAR (current_buffer, scroll_up_aggressively);
18576 height = WINDOW_BOX_TEXT_HEIGHT (w);
18577 if (NUMBERP (aggressive))
18578 {
18579 double float_amount = XFLOATINT (aggressive) * height;
18580 int aggressive_scroll = float_amount;
18581 if (aggressive_scroll == 0 && float_amount > 0)
18582 aggressive_scroll = 1;
18583
18584
18585
18586
18587
18588
18589 if (aggressive_scroll + 2 * this_scroll_margin > height)
18590 aggressive_scroll = height - 2 * this_scroll_margin;
18591 amount_to_scroll = dy + aggressive_scroll;
18592 }
18593 }
18594
18595 if (amount_to_scroll <= 0)
18596 return SCROLLING_FAILED;
18597
18598 start_display (&it, w, startp);
18599 if (arg_scroll_conservatively <= scroll_limit)
18600 move_it_vertically (&it, amount_to_scroll);
18601 else
18602 {
18603
18604
18605
18606
18607
18608
18609 struct it it1;
18610 void *it1data = NULL;
18611
18612
18613 int start_y;
18614
18615 SAVE_IT (it1, it, it1data);
18616 start_y = line_bottom_y (&it1);
18617 do {
18618 RESTORE_IT (&it, &it, it1data);
18619 move_it_by_lines (&it, 1);
18620 SAVE_IT (it1, it, it1data);
18621 } while (IT_CHARPOS (it) < ZV
18622 && line_bottom_y (&it1) - start_y < amount_to_scroll);
18623 bidi_unshelve_cache (it1data, true);
18624 }
18625
18626
18627 if (IT_CHARPOS (it) == CHARPOS (startp))
18628 move_it_by_lines (&it, 1);
18629 startp = it.current.pos;
18630 }
18631 else
18632 {
18633 struct text_pos scroll_margin_pos = startp;
18634 int y_offset = 0;
18635
18636
18637
18638 if (this_scroll_margin)
18639 {
18640 int y_start;
18641
18642 start_display (&it, w, startp);
18643 y_start = it.current_y;
18644 move_it_vertically (&it, this_scroll_margin);
18645 scroll_margin_pos = it.current.pos;
18646
18647
18648
18649 if (IT_CHARPOS (it) == ZV
18650 && it.current_y - y_start < this_scroll_margin)
18651 y_offset = this_scroll_margin - (it.current_y - y_start);
18652 }
18653
18654 if (PT < CHARPOS (scroll_margin_pos))
18655 {
18656
18657
18658 int y0, y_to_move;
18659
18660
18661
18662
18663
18664
18665 SET_TEXT_POS (pos, PT, PT_BYTE);
18666 start_display (&it, w, pos);
18667 y0 = it.current_y;
18668 y_to_move = max (it.last_visible_y,
18669 max (scroll_max, 10 * frame_line_height));
18670 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
18671 y_to_move, -1,
18672 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18673 dy = it.current_y - y0;
18674 if (dy > scroll_max
18675 || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
18676 return SCROLLING_FAILED;
18677
18678
18679 dy += y_offset;
18680
18681
18682 start_display (&it, w, startp);
18683
18684 if (arg_scroll_conservatively)
18685 amount_to_scroll
18686 = min (max (dy, frame_line_height),
18687 frame_line_height * arg_scroll_conservatively);
18688 else if (scroll_step || temp_scroll_step)
18689 amount_to_scroll = scroll_max;
18690 else
18691 {
18692 aggressive = BVAR (current_buffer, scroll_down_aggressively);
18693 height = WINDOW_BOX_TEXT_HEIGHT (w);
18694 if (NUMBERP (aggressive))
18695 {
18696 double float_amount = XFLOATINT (aggressive) * height;
18697 int aggressive_scroll = float_amount;
18698 if (aggressive_scroll == 0 && float_amount > 0)
18699 aggressive_scroll = 1;
18700
18701
18702
18703
18704 if (aggressive_scroll + 2 * this_scroll_margin > height)
18705 aggressive_scroll = height - 2 * this_scroll_margin;
18706 amount_to_scroll = dy + aggressive_scroll;
18707 }
18708 }
18709
18710 if (amount_to_scroll <= 0)
18711 return SCROLLING_FAILED;
18712
18713 move_it_vertically_backward (&it, amount_to_scroll);
18714 startp = it.current.pos;
18715 }
18716 }
18717
18718
18719 startp = run_window_scroll_functions (window, startp);
18720
18721
18722
18723 if (!try_window (window, startp, 0))
18724 rc = SCROLLING_NEED_LARGER_MATRICES;
18725 else if (w->cursor.vpos < 0)
18726 {
18727 clear_glyph_matrix (w->desired_matrix);
18728 rc = SCROLLING_FAILED;
18729 }
18730 else
18731 {
18732
18733 if (!just_this_one_p
18734 || current_buffer->clip_changed
18735 || BEG_UNCHANGED < CHARPOS (startp))
18736 w->base_line_number = 0;
18737
18738
18739
18740 if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1,
18741 false, false)
18742
18743
18744
18745 && extra_scroll_margin_lines < w->desired_matrix->nrows - 1)
18746 {
18747 clear_glyph_matrix (w->desired_matrix);
18748 ++extra_scroll_margin_lines;
18749 goto too_near_end;
18750 }
18751 rc = SCROLLING_SUCCESS;
18752 }
18753
18754 return rc;
18755 }
18756
18757
18758
18759
18760
18761
18762
18763
18764
18765
18766
18767
18768 static bool
18769 compute_window_start_on_continuation_line (struct window *w)
18770 {
18771 struct text_pos pos, start_pos, pos_before_pt;
18772 bool window_start_changed_p = false;
18773
18774 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
18775
18776
18777
18778
18779 if (CHARPOS (start_pos) > BEGV
18780 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
18781 {
18782 struct it it;
18783 struct glyph_row *row;
18784
18785
18786 if (CHARPOS (start_pos) < BEGV)
18787 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
18788 else if (CHARPOS (start_pos) > ZV)
18789 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
18790
18791
18792
18793 row = w->desired_matrix->rows + window_wants_tab_line (w)
18794 + window_wants_header_line (w);
18795 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
18796 row, DEFAULT_FACE_ID);
18797 reseat_at_previous_visible_line_start (&it);
18798
18799
18800
18801
18802
18803
18804
18805 if (IT_CHARPOS (it) <= PT
18806 && (CHARPOS (start_pos) - IT_CHARPOS (it)
18807
18808 < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w)))
18809 {
18810 int min_distance, distance;
18811
18812
18813
18814
18815
18816
18817
18818 pos_before_pt = pos = it.current.pos;
18819 min_distance = DISP_INFINITY;
18820 while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
18821 distance < min_distance)
18822 {
18823 min_distance = distance;
18824 if (CHARPOS (pos) <= PT)
18825 pos_before_pt = pos;
18826 pos = it.current.pos;
18827 if (it.line_wrap == WORD_WRAP)
18828 {
18829
18830
18831
18832
18833
18834
18835
18836
18837
18838 move_it_to (&it, ZV, it.last_visible_x, it.current_y, -1,
18839 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18840 move_it_to (&it, ZV, 0,
18841 it.current_y + it.max_ascent + it.max_descent, -1,
18842 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18843 }
18844 else
18845 move_it_by_lines (&it, 1);
18846 }
18847
18848
18849
18850
18851
18852 if (CHARPOS (pos) > PT)
18853 pos = pos_before_pt;
18854
18855
18856 SET_MARKER_FROM_TEXT_POS (w->start, pos);
18857 window_start_changed_p = true;
18858 }
18859 }
18860
18861 return window_start_changed_p;
18862 }
18863
18864
18865
18866
18867
18868
18869
18870
18871
18872
18873
18874
18875
18876
18877
18878
18879
18880 enum
18881 {
18882 CURSOR_MOVEMENT_SUCCESS,
18883 CURSOR_MOVEMENT_CANNOT_BE_USED,
18884 CURSOR_MOVEMENT_MUST_SCROLL,
18885 CURSOR_MOVEMENT_NEED_LARGER_MATRICES
18886 };
18887
18888 static int
18889 try_cursor_movement (Lisp_Object window, struct text_pos startp,
18890 bool *scroll_step)
18891 {
18892 struct window *w = XWINDOW (window);
18893 struct frame *f = XFRAME (w->frame);
18894 int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
18895
18896 #ifdef GLYPH_DEBUG
18897 if (inhibit_try_cursor_movement)
18898 return rc;
18899 #endif
18900
18901
18902
18903
18904 eassert (w->last_point > 0);
18905
18906
18907
18908 eassert (!w->window_end_valid
18909 || w->window_end_vpos < w->current_matrix->nrows);
18910
18911
18912
18913 if (
18914 PT >= CHARPOS (startp)
18915
18916 && !current_buffer->clip_changed
18917
18918
18919
18920
18921 && !update_mode_lines
18922 && !windows_or_buffers_changed
18923 && !f->cursor_type_changed
18924 && NILP (Vshow_trailing_whitespace)
18925
18926
18927 && !EQ (Vdisplay_line_numbers, Qrelative)
18928 && !EQ (Vdisplay_line_numbers, Qvisual)
18929
18930
18931
18932 && !(!NILP (Vdisplay_line_numbers)
18933 && NILP (Finternal_lisp_face_equal_p (Qline_number,
18934 Qline_number_current_line,
18935 w->frame)))
18936
18937
18938
18939
18940
18941
18942 && !EQ (window, minibuf_window)
18943
18944
18945
18946 && !overlay_arrow_in_current_buffer_p ())
18947 {
18948 int this_scroll_margin, top_scroll_margin;
18949 struct glyph_row *row = NULL;
18950
18951 #ifdef GLYPH_DEBUG
18952 debug_method_add (w, "cursor movement");
18953 #endif
18954
18955 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18956
18957 top_scroll_margin = this_scroll_margin;
18958 if (window_wants_tab_line (w))
18959 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
18960 if (window_wants_header_line (w))
18961 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
18962
18963
18964
18965 if (w->last_cursor_vpos < 0
18966 || w->last_cursor_vpos >= w->current_matrix->nrows)
18967 rc = CURSOR_MOVEMENT_MUST_SCROLL;
18968 else
18969 {
18970 row = MATRIX_ROW (w->current_matrix, w->last_cursor_vpos);
18971
18972 if (row->tab_line_p)
18973 ++row;
18974 if (row->mode_line_p)
18975 ++row;
18976 if (!row->enabled_p)
18977 rc = CURSOR_MOVEMENT_MUST_SCROLL;
18978 }
18979
18980 if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
18981 {
18982 bool scroll_p = false, must_scroll = false;
18983 int last_y = window_text_bottom_y (w) - this_scroll_margin;
18984
18985 if (PT > w->last_point)
18986 {
18987
18988 while (MATRIX_ROW_END_CHARPOS (row) < PT
18989 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
18990 {
18991 eassert (row->enabled_p);
18992 ++row;
18993 }
18994
18995
18996
18997
18998 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
18999 && MATRIX_ROW_END_CHARPOS (row) == PT
19000 && row < MATRIX_MODE_LINE_ROW (w->current_matrix)
19001 && MATRIX_ROW_START_CHARPOS (row+1) >= PT
19002 && !cursor_row_p (row))
19003 ++row;
19004
19005
19006
19007
19008
19009 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
19010 || PT > MATRIX_ROW_END_CHARPOS (row)
19011
19012
19013 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19014 && PT == MATRIX_ROW_END_CHARPOS (row)
19015 && !row->ends_at_zv_p
19016 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19017 scroll_p = true;
19018 }
19019 else if (PT < w->last_point)
19020 {
19021
19022
19023 struct glyph_row *row0 = row;
19024
19025 while (!row->mode_line_p
19026 && (MATRIX_ROW_START_CHARPOS (row) > PT
19027 || (MATRIX_ROW_START_CHARPOS (row) == PT
19028 && (MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)
19029 || (
19030 row > w->current_matrix->rows
19031 && (row-1)->ends_in_newline_from_string_p))))
19032 && (row->y > top_scroll_margin
19033 || CHARPOS (startp) == BEGV))
19034 {
19035 eassert (row->enabled_p);
19036 --row;
19037 }
19038
19039
19040
19041
19042
19043 if (!(MATRIX_ROW_START_CHARPOS (row) <= PT
19044 && PT <= MATRIX_ROW_END_CHARPOS (row))
19045 && row0->continued_p)
19046 {
19047 row = row0;
19048 while (MATRIX_ROW_START_CHARPOS (row) > PT
19049 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19050 {
19051 eassert (row->enabled_p);
19052 ++row;
19053 }
19054 }
19055
19056
19057
19058
19059
19060
19061 if (row < w->current_matrix->rows
19062 || row->mode_line_p)
19063 {
19064 row = w->current_matrix->rows;
19065
19066 if (row->tab_line_p)
19067 ++row;
19068 if (row->mode_line_p)
19069 ++row;
19070 }
19071
19072
19073
19074 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19075 && MATRIX_ROW_END_CHARPOS (row) == PT
19076 && !cursor_row_p (row))
19077 ++row;
19078
19079
19080
19081 if ((row->y < top_scroll_margin
19082 && CHARPOS (startp) != BEGV)
19083 || MATRIX_ROW_BOTTOM_Y (row) > last_y
19084 || PT > MATRIX_ROW_END_CHARPOS (row)
19085 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19086 && PT == MATRIX_ROW_END_CHARPOS (row)
19087 && !row->ends_at_zv_p
19088 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19089 scroll_p = true;
19090 }
19091 else
19092 {
19093
19094
19095 rc = CURSOR_MOVEMENT_SUCCESS;
19096 }
19097
19098 if ((PT < MATRIX_ROW_START_CHARPOS (row)
19099 && (row == MATRIX_FIRST_TEXT_ROW (w->current_matrix)
19100
19101
19102 || (MATRIX_ROW_END_CHARPOS (row-1)
19103 == MATRIX_ROW_START_CHARPOS (row))))
19104 || PT > MATRIX_ROW_END_CHARPOS (row))
19105 {
19106
19107 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19108 must_scroll = true;
19109 }
19110 else if (rc != CURSOR_MOVEMENT_SUCCESS
19111 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19112 {
19113 struct glyph_row *row1;
19114
19115
19116
19117
19118
19119
19120
19121
19122
19123
19124
19125 for (row1 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19126 MATRIX_ROW_CONTINUATION_LINE_P (row);
19127 --row)
19128 {
19129
19130
19131
19132 if (row <= row1)
19133 {
19134 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19135 break;
19136 }
19137 eassert (row->enabled_p);
19138 }
19139 }
19140 if (must_scroll)
19141 ;
19142 else if (rc != CURSOR_MOVEMENT_SUCCESS
19143 && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
19144
19145
19146
19147 && !row->mode_line_p
19148 && !cursor_row_fully_visible_p (w, true, true, true))
19149 {
19150 if (PT == MATRIX_ROW_END_CHARPOS (row)
19151 && !row->ends_at_zv_p
19152 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
19153 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19154 else if (row->height > window_box_height (w))
19155 {
19156
19157
19158
19159
19160 *scroll_step = true;
19161 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19162 }
19163 else
19164 {
19165 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
19166 if (!cursor_row_fully_visible_p (w, false, true, false))
19167 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19168 else
19169 rc = CURSOR_MOVEMENT_SUCCESS;
19170 }
19171 }
19172 else if (scroll_p)
19173 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19174 else if (rc != CURSOR_MOVEMENT_SUCCESS
19175 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19176 {
19177
19178
19179
19180
19181
19182
19183
19184 bool rv = false;
19185 bool pt_invis = false;
19186 Lisp_Object val = get_char_property_and_overlay (make_fixnum (PT),
19187 Qinvisible,
19188 Qnil, NULL);
19189
19190 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
19191 pt_invis = true;
19192
19193 do
19194 {
19195 bool at_zv_p = false, exact_match_p = false;
19196
19197
19198
19199
19200
19201 if ((pt_invis || MATRIX_ROW_START_CHARPOS (row) <= PT)
19202 && PT <= MATRIX_ROW_END_CHARPOS (row)
19203 && cursor_row_p (row))
19204 rv |= set_cursor_from_row (w, row, w->current_matrix,
19205 0, 0, 0, 0);
19206
19207
19208
19209 if (rv)
19210 {
19211 at_zv_p = MATRIX_ROW (w->current_matrix,
19212 w->cursor.vpos)->ends_at_zv_p;
19213 if (!at_zv_p
19214 && w->cursor.hpos >= 0
19215 && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix,
19216 w->cursor.vpos))
19217 {
19218 struct glyph_row *candidate =
19219 MATRIX_ROW (w->current_matrix, w->cursor.vpos);
19220 struct glyph *g =
19221 candidate->glyphs[TEXT_AREA] + w->cursor.hpos;
19222 ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate);
19223
19224 exact_match_p =
19225 (BUFFERP (g->object) && g->charpos == PT)
19226 || (NILP (g->object)
19227 && (g->charpos == PT
19228 || (g->charpos == 0 && endpos - 1 == PT)));
19229
19230
19231
19232
19233 if (!exact_match_p && pt_invis)
19234 exact_match_p = true;
19235 }
19236 if (at_zv_p || exact_match_p)
19237 {
19238 rc = CURSOR_MOVEMENT_SUCCESS;
19239 break;
19240 }
19241 }
19242 if (MATRIX_ROW_BOTTOM_Y (row) == last_y)
19243 break;
19244 ++row;
19245 }
19246 while (((MATRIX_ROW_CONTINUATION_LINE_P (row)
19247 || row->continued_p)
19248 && MATRIX_ROW_BOTTOM_Y (row) <= last_y)
19249 || (MATRIX_ROW_START_CHARPOS (row) == PT
19250 && MATRIX_ROW_BOTTOM_Y (row) < last_y));
19251
19252
19253
19254 if (rc != CURSOR_MOVEMENT_SUCCESS
19255 && !(rv
19256 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
19257 && !row->continued_p))
19258 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19259 else if (rv)
19260 rc = CURSOR_MOVEMENT_SUCCESS;
19261 }
19262 else
19263 {
19264 do
19265 {
19266 if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0))
19267 {
19268 rc = CURSOR_MOVEMENT_SUCCESS;
19269 break;
19270 }
19271 ++row;
19272 }
19273 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19274 && MATRIX_ROW_START_CHARPOS (row) == PT
19275 && cursor_row_p (row));
19276 }
19277 }
19278 }
19279
19280 return rc;
19281 }
19282
19283
19284 void
19285 set_vertical_scroll_bar (struct window *w)
19286 {
19287 ptrdiff_t start, end, whole;
19288
19289
19290
19291
19292
19293
19294
19295
19296 if (!MINI_WINDOW_P (w)
19297 || (w == XWINDOW (minibuf_window)
19298 && NILP (echo_area_buffer[0])))
19299 {
19300 struct buffer *buf = XBUFFER (w->contents);
19301
19302 whole = BUF_ZV (buf) - BUF_BEGV (buf);
19303 start = marker_position (w->start) - BUF_BEGV (buf);
19304 end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
19305
19306
19307
19308
19309 if (!w->window_end_valid && !buf->long_line_optimizations_p)
19310 {
19311 struct it it;
19312 struct text_pos start_pos;
19313 struct buffer *obuf = current_buffer;
19314
19315
19316
19317 set_buffer_internal_1 (XBUFFER (w->contents));
19318 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
19319 start_display (&it, w, start_pos);
19320 move_it_to (&it, -1, it.last_visible_x, window_box_height (w), -1,
19321 MOVE_TO_X | MOVE_TO_Y);
19322 end -= (BUF_Z (buf) - IT_CHARPOS (it)) - w->window_end_pos;
19323 set_buffer_internal_1 (obuf);
19324 }
19325
19326 if (end < start)
19327 end = start;
19328 if (whole < (end - start))
19329 whole = end - start;
19330 }
19331 else
19332 start = end = whole = 0;
19333
19334
19335 if (FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19336 (*FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19337 (w, end - start, whole, start);
19338 }
19339
19340
19341 void
19342 set_horizontal_scroll_bar (struct window *w)
19343 {
19344 int start, end, whole, portion;
19345
19346 if (!MINI_WINDOW_P (w) || EQ (w->horizontal_scroll_bar_type, Qbottom))
19347 {
19348 struct buffer *b = XBUFFER (w->contents);
19349 struct buffer *old_buffer = NULL;
19350 struct it it;
19351 struct text_pos startp;
19352
19353 if (b != current_buffer)
19354 {
19355 old_buffer = current_buffer;
19356 set_buffer_internal (b);
19357 }
19358
19359 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19360 start_display (&it, w, startp);
19361 it.last_visible_x = INT_MAX;
19362 whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1,
19363 MOVE_TO_X | MOVE_TO_Y);
19364
19365
19366
19367
19368 start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
19369 end = start + window_box_width (w, TEXT_AREA);
19370 portion = end - start;
19371
19372
19373
19374
19375 whole = max (whole, end);
19376
19377 if (it.bidi_p)
19378 {
19379 Lisp_Object pdir;
19380
19381 pdir = Fcurrent_bidi_paragraph_direction (Qnil);
19382 if (EQ (pdir, Qright_to_left))
19383 {
19384 start = whole - end;
19385 end = start + portion;
19386 }
19387 }
19388
19389 if (old_buffer)
19390 set_buffer_internal (old_buffer);
19391 }
19392 else
19393 start = end = whole = portion = 0;
19394
19395 w->hscroll_whole = whole;
19396
19397
19398 if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19399 (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19400 (w, portion, whole, start);
19401 }
19402
19403
19404
19405 static bool
19406 window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp)
19407 {
19408 if (!make_window_start_visible)
19409 return true;
19410
19411 struct window *w = XWINDOW (window);
19412 struct frame *f = XFRAME (w->frame);
19413 Lisp_Object startpos = make_fixnum (startp);
19414 Lisp_Object invprop, disp_spec;
19415 struct text_pos ignored;
19416
19417
19418 if ((invprop = Fget_char_property (startpos, Qinvisible, window)),
19419 TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19420 return false;
19421
19422
19423 if (!NILP (disp_spec = Fget_char_property (startpos, Qdisplay, window))
19424 && handle_display_spec (NULL, disp_spec, Qnil, Qnil, &ignored, startp,
19425 FRAME_WINDOW_P (f)) > 0)
19426 return false;
19427
19428 return true;
19429 }
19430
19431 DEFUN ("long-line-optimizations-p", Flong_line_optimizations_p, Slong_line_optimizations_p,
19432 0, 0, 0,
19433 doc:
19434
19435 )
19436 (void)
19437 {
19438 return current_buffer->long_line_optimizations_p ? Qt : Qnil;
19439 }
19440
19441
19442
19443
19444
19445
19446
19447
19448
19449
19450
19451
19452
19453
19454
19455
19456
19457
19458
19459
19460
19461
19462
19463
19464
19465
19466
19467
19468
19469
19470
19471
19472
19473
19474
19475
19476
19477
19478
19479
19480
19481
19482
19483
19484
19485
19486
19487
19488
19489
19490
19491 static void
19492 redisplay_window (Lisp_Object window, bool just_this_one_p)
19493 {
19494 struct window *w = XWINDOW (window);
19495 struct frame *f = XFRAME (w->frame);
19496 struct buffer *buffer = XBUFFER (w->contents);
19497 struct buffer *old = current_buffer;
19498 struct text_pos lpoint, opoint, startp;
19499 bool update_mode_line;
19500 int tem;
19501 struct it it;
19502
19503 bool current_matrix_up_to_date_p = false;
19504 bool used_current_matrix_p = false;
19505
19506
19507 bool buffer_unchanged_p = false;
19508 bool temp_scroll_step = false;
19509 specpdl_ref count = SPECPDL_INDEX ();
19510 int rc;
19511 int centering_position = -1;
19512 bool last_line_misfit = false;
19513 ptrdiff_t beg_unchanged, end_unchanged;
19514 int frame_line_height, margin;
19515 bool use_desired_matrix;
19516 void *itdata = NULL;
19517
19518 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19519 opoint = lpoint;
19520
19521 #ifdef GLYPH_DEBUG
19522 *w->desired_matrix->method = 0;
19523 #endif
19524
19525 if (!just_this_one_p && needs_no_redisplay (w))
19526 return;
19527
19528
19529 eassert (XMARKER (w->start)->buffer == buffer);
19530 eassert (XMARKER (w->pointm)->buffer == buffer);
19531
19532 reconsider_clip_changes (w);
19533 frame_line_height = default_line_pixel_height (w);
19534 margin = window_scroll_margin (w, MARGIN_IN_LINES);
19535
19536
19537
19538 update_mode_line = (w->update_mode_line
19539 || update_mode_lines
19540 || buffer->clip_changed
19541 || buffer->prevent_redisplay_optimizations_p);
19542
19543 if (!just_this_one_p)
19544
19545
19546 w->must_be_updated_p = true;
19547
19548 if (MINI_WINDOW_P (w))
19549 {
19550 if (w == XWINDOW (echo_area_window)
19551 && !NILP (echo_area_buffer[0]))
19552 {
19553 if (update_mode_line)
19554
19555
19556 goto finish_menu_bars;
19557 else
19558
19559 goto finish_scroll_bars;
19560 }
19561 else if ((w != XWINDOW (minibuf_window)
19562 || minibuf_level == 0)
19563
19564 && BUF_Z (XBUFFER (w->contents)) == BUF_BEG (XBUFFER (w->contents))
19565
19566
19567 && !NILP (Fmemq (w->contents, Vminibuffer_list)))
19568 {
19569
19570
19571 int yb = window_text_bottom_y (w);
19572 struct glyph_row *row;
19573 int y;
19574
19575 for (y = 0, row = w->desired_matrix->rows;
19576 y < yb;
19577 y += row->height, ++row)
19578 blank_row (w, row, y);
19579 goto finish_scroll_bars;
19580 }
19581 else if (minibuf_level >= 1)
19582 {
19583
19584
19585
19586 resize_mini_window (w, false);
19587 }
19588
19589 clear_glyph_matrix (w->desired_matrix);
19590 }
19591
19592
19593
19594
19595
19596 set_buffer_internal_1 (XBUFFER (w->contents));
19597
19598 current_matrix_up_to_date_p
19599 = (w->window_end_valid
19600 && !current_buffer->clip_changed
19601 && !current_buffer->prevent_redisplay_optimizations_p
19602 && !window_outdated (w)
19603 && !composition_break_at_point
19604 && !hscrolling_current_line_p (w));
19605
19606 beg_unchanged = BEG_UNCHANGED;
19607 end_unchanged = END_UNCHANGED;
19608
19609 SET_TEXT_POS (opoint, PT, PT_BYTE);
19610
19611 specbind (Qinhibit_point_motion_hooks, Qt);
19612
19613 buffer_unchanged_p
19614 = (w->window_end_valid
19615 && !current_buffer->clip_changed
19616 && !window_outdated (w));
19617
19618
19619
19620 if (windows_or_buffers_changed)
19621 {
19622
19623
19624 if (XMARKER (w->start)->buffer == current_buffer)
19625 compute_window_start_on_continuation_line (w);
19626
19627 w->window_end_valid = false;
19628
19629
19630 current_matrix_up_to_date_p = false;
19631 }
19632
19633
19634 CHECK_WINDOW_END (w);
19635 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
19636 emacs_abort ();
19637 if (BYTEPOS (opoint) < CHARPOS (opoint))
19638 emacs_abort ();
19639
19640 if (mode_line_update_needed (w))
19641 update_mode_line = true;
19642
19643
19644
19645 if (!EQ (window, selected_window))
19646 {
19647 ptrdiff_t new_pt = marker_position (w->pointm);
19648 ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
19649
19650 if (new_pt < BEGV)
19651 {
19652 new_pt = BEGV;
19653 new_pt_byte = BEGV_BYTE;
19654 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
19655 }
19656 else if (new_pt > (ZV - 1))
19657 {
19658 new_pt = ZV;
19659 new_pt_byte = ZV_BYTE;
19660 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
19661 }
19662
19663
19664 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
19665 }
19666
19667
19668
19669
19670
19671
19672 if (current_buffer->width_run_cache
19673 || (current_buffer->base_buffer
19674 && current_buffer->base_buffer->width_run_cache))
19675 {
19676 struct Lisp_Char_Table *disptab = buffer_display_table ();
19677
19678 if (! disptab_matches_widthtab
19679 (disptab, XVECTOR (BVAR (current_buffer, width_table))))
19680 {
19681 struct buffer *buf = current_buffer;
19682
19683 if (buf->base_buffer)
19684 buf = buf->base_buffer;
19685 invalidate_region_cache (buf, buf->width_run_cache, BEG, Z);
19686 recompute_width_table (current_buffer, disptab);
19687 }
19688 }
19689
19690
19691 if (!NILP (Vlong_line_threshold)
19692 && !current_buffer->long_line_optimizations_p
19693 && (CHARS_MODIFF - UNCHANGED_MODIFIED > 8
19694 || current_buffer->clip_changed))
19695 {
19696 ptrdiff_t cur, next, found, max = 0, threshold;
19697 threshold = XFIXNUM (Vlong_line_threshold);
19698 for (cur = BEGV; cur < ZV; cur = next)
19699 {
19700 next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
19701 &found, NULL, true);
19702 if (next - cur > max) max = next - cur;
19703 if (!found || max > threshold) break;
19704 }
19705 if (max > threshold)
19706 current_buffer->long_line_optimizations_p = true;
19707 }
19708
19709
19710 if (XMARKER (w->start)->buffer != current_buffer)
19711 goto recenter;
19712
19713 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19714
19715
19716
19717 if ((w->optional_new_start || window_frozen_p (w))
19718 && CHARPOS (startp) >= BEGV
19719 && CHARPOS (startp) <= ZV)
19720 {
19721 ptrdiff_t it_charpos;
19722
19723 w->optional_new_start = false;
19724 if (!w->force_start)
19725 {
19726 start_display (&it, w, startp);
19727 move_it_to (&it, PT, 0, it.last_visible_y, -1,
19728 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19729
19730
19731 it_charpos = IT_CHARPOS (it);
19732
19733
19734
19735
19736
19737 if (it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y)
19738 {
19739 if (it_charpos == PT)
19740 w->force_start = true;
19741
19742 else if (it_charpos > PT && CHARPOS (startp) <= PT)
19743 w->force_start = true;
19744 #ifdef GLYPH_DEBUG
19745 if (w->force_start)
19746 {
19747 if (window_frozen_p (w))
19748 debug_method_add (w, "set force_start from frozen window start");
19749 else
19750 debug_method_add (w, "set force_start from optional_new_start");
19751 }
19752 #endif
19753 }
19754 }
19755 }
19756
19757 force_start:
19758
19759
19760
19761 if (w->force_start)
19762 {
19763
19764 int new_vpos = -1;
19765
19766 w->force_start = false;
19767
19768
19769
19770
19771 if (!w->preserve_vscroll_p || !window_frozen_p (w))
19772 w->vscroll = 0;
19773
19774 w->preserve_vscroll_p = false;
19775 w->window_end_valid = false;
19776
19777
19778 if (!buffer_unchanged_p)
19779 w->base_line_number = 0;
19780
19781
19782
19783
19784
19785
19786
19787
19788 if (!update_mode_line
19789 || ! NILP (Vwindow_scroll_functions))
19790 {
19791 update_mode_line = true;
19792 w->update_mode_line = true;
19793 startp = run_window_scroll_functions (window, startp);
19794 }
19795
19796 if (CHARPOS (startp) < BEGV)
19797 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
19798 else if (CHARPOS (startp) > ZV)
19799 SET_TEXT_POS (startp, ZV, ZV_BYTE);
19800
19801
19802
19803 if (!window_start_acceptable_p (window, CHARPOS (startp)))
19804 goto ignore_start;
19805
19806
19807
19808
19809
19810
19811 clear_glyph_matrix (w->desired_matrix);
19812 if (!try_window (window, startp, 0))
19813 {
19814 w->force_start = true;
19815 clear_glyph_matrix (w->desired_matrix);
19816 goto need_larger_matrices;
19817 }
19818
19819 if (w->cursor.vpos < 0)
19820 {
19821
19822
19823
19824
19825
19826 struct glyph_row *r = NULL;
19827 Lisp_Object invprop =
19828 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
19829 Qnil, NULL);
19830
19831 if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19832 {
19833 ptrdiff_t alt_pt;
19834 Lisp_Object invprop_end =
19835 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
19836 Qnil, Qnil);
19837
19838 if (FIXNATP (invprop_end))
19839 alt_pt = XFIXNAT (invprop_end);
19840 else
19841 alt_pt = ZV;
19842 r = row_containing_pos (w, alt_pt, w->desired_matrix->rows,
19843 NULL, 0);
19844 }
19845 if (r)
19846 new_vpos = MATRIX_ROW_BOTTOM_Y (r);
19847 else
19848 new_vpos = window_box_height (w) / 2;
19849 }
19850
19851 if (!cursor_row_fully_visible_p (w, false, false, false))
19852 {
19853
19854
19855 new_vpos = window_box_height (w);
19856
19857
19858
19859
19860
19861
19862 if (new_vpos >= w->cursor.y)
19863 {
19864 w->cursor.vpos = -1;
19865 clear_glyph_matrix (w->desired_matrix);
19866 goto try_to_scroll;
19867 }
19868 }
19869 else if (w->cursor.vpos >= 0)
19870 {
19871
19872
19873
19874 int pixel_margin = margin * frame_line_height;
19875 bool tab_line = window_wants_tab_line (w);
19876 bool header_line = window_wants_header_line (w);
19877
19878
19879
19880
19881
19882 if (w->cursor.vpos < margin + tab_line + header_line)
19883 {
19884 w->cursor.vpos = -1;
19885 clear_glyph_matrix (w->desired_matrix);
19886 goto try_to_scroll;
19887 }
19888 else
19889 {
19890 int window_height = window_box_height (w);
19891
19892 if (tab_line)
19893 window_height += CURRENT_TAB_LINE_HEIGHT (w);
19894 if (header_line)
19895 window_height += CURRENT_HEADER_LINE_HEIGHT (w);
19896 if (w->cursor.y >= window_height - pixel_margin)
19897 {
19898 w->cursor.vpos = -1;
19899 clear_glyph_matrix (w->desired_matrix);
19900 goto try_to_scroll;
19901 }
19902 }
19903 }
19904
19905
19906
19907 if (new_vpos >= 0)
19908 {
19909 struct glyph_row *row;
19910
19911 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
19912 while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos
19913 && !row->ends_at_zv_p)
19914 ++row;
19915
19916 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
19917 MATRIX_ROW_START_BYTEPOS (row));
19918
19919 if (w != XWINDOW (selected_window))
19920 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
19921 else if (current_buffer == old)
19922 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19923
19924 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
19925
19926
19927
19928
19929
19930
19931
19932 w->redisplay = false;
19933 XBUFFER (w->contents)->text->redisplay = false;
19934 safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
19935
19936 if (w->redisplay || XBUFFER (w->contents)->text->redisplay
19937 || ((EQ (Vdisplay_line_numbers, Qrelative)
19938 || EQ (Vdisplay_line_numbers, Qvisual))
19939 && row != MATRIX_FIRST_TEXT_ROW (w->desired_matrix)))
19940 {
19941
19942
19943
19944
19945 clear_glyph_matrix (w->desired_matrix);
19946 if (!try_window (window, startp, 0))
19947 goto need_larger_matrices;
19948 }
19949 }
19950 if (w->cursor.vpos < 0
19951 || !cursor_row_fully_visible_p (w, false, false, false))
19952 {
19953 clear_glyph_matrix (w->desired_matrix);
19954 goto try_to_scroll;
19955 }
19956
19957 #ifdef GLYPH_DEBUG
19958 debug_method_add (w, "forced window start");
19959 #endif
19960 goto done;
19961 }
19962
19963 ignore_start:
19964
19965
19966
19967
19968 if (current_matrix_up_to_date_p
19969 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
19970 rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
19971 {
19972 switch (rc)
19973 {
19974 case CURSOR_MOVEMENT_SUCCESS:
19975 used_current_matrix_p = true;
19976 goto done;
19977
19978 case CURSOR_MOVEMENT_MUST_SCROLL:
19979 goto try_to_scroll;
19980
19981 default:
19982 emacs_abort ();
19983 }
19984 }
19985
19986
19987
19988 else if (w->start_at_line_beg
19989 && ((CHARPOS (startp) > BEGV
19990 && FETCH_BYTE (BYTEPOS (startp) - 1) != '\n')
19991 || (CHARPOS (startp) >= BEGV
19992 && CHARPOS (startp) <= ZV
19993 && !window_start_acceptable_p (window, CHARPOS (startp)))))
19994 {
19995 #ifdef GLYPH_DEBUG
19996 debug_method_add (w, "recenter 1");
19997 #endif
19998 goto recenter;
19999 }
20000
20001
20002
20003
20004 else if ((tem = try_window_id (w)) != 0)
20005 {
20006 #ifdef GLYPH_DEBUG
20007 debug_method_add (w, "try_window_id %d", tem);
20008 #endif
20009
20010 if (f->fonts_changed)
20011 goto need_larger_matrices;
20012 if (tem > 0)
20013 goto done;
20014
20015
20016
20017 }
20018 else if (CHARPOS (startp) >= BEGV
20019 && CHARPOS (startp) <= ZV
20020 && PT >= CHARPOS (startp)
20021 && (CHARPOS (startp) < ZV
20022
20023 || CHARPOS (startp) == BEGV
20024 || !window_outdated (w)))
20025 {
20026 int d1, d2, d5, d6;
20027 int rtop, rbot;
20028
20029
20030
20031
20032
20033
20034
20035
20036
20037
20038 if (!w->start_at_line_beg
20039 && NILP (track_mouse)
20040 && CHARPOS (startp) > BEGV
20041 && CHARPOS (startp) > BEG + beg_unchanged
20042 && CHARPOS (startp) <= Z - end_unchanged
20043
20044
20045
20046
20047
20048 && XMARKER (w->start)->buffer == current_buffer
20049 && compute_window_start_on_continuation_line (w)
20050
20051
20052
20053
20054
20055
20056 && pos_visible_p (w, PT, &d1, &d2, &rtop, &rbot, &d5, &d6)
20057
20058
20059 && (rtop != 0) == (rbot != 0))
20060 {
20061 w->force_start = true;
20062 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20063 #ifdef GLYPH_DEBUG
20064 debug_method_add (w, "recomputed window start in continuation line");
20065 #endif
20066 goto force_start;
20067 }
20068
20069
20070
20071
20072 if (!window_start_acceptable_p (window, CHARPOS (startp)))
20073 {
20074 #ifdef GLYPH_DEBUG
20075 debug_method_add (w, "recenter 2");
20076 #endif
20077 goto recenter;
20078 }
20079
20080 #ifdef GLYPH_DEBUG
20081 debug_method_add (w, "same window start");
20082 #endif
20083
20084
20085
20086 if (!current_matrix_up_to_date_p
20087
20088
20089
20090 || !NILP (Vwindow_scroll_functions)
20091 || MINI_WINDOW_P (w)
20092 || !(used_current_matrix_p
20093 = try_window_reusing_current_matrix (w)))
20094 {
20095 IF_DEBUG (debug_method_add (w, "1"));
20096 clear_glyph_matrix (w->desired_matrix);
20097 if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
20098
20099
20100
20101 goto try_to_scroll;
20102 }
20103
20104 if (f->fonts_changed)
20105 goto need_larger_matrices;
20106
20107 if (w->cursor.vpos >= 0)
20108 {
20109 if (!just_this_one_p
20110 || current_buffer->clip_changed
20111 || BEG_UNCHANGED < CHARPOS (startp))
20112
20113 w->base_line_number = 0;
20114
20115 if (!cursor_row_fully_visible_p (w, true, false, false))
20116 {
20117 clear_glyph_matrix (w->desired_matrix);
20118 last_line_misfit = true;
20119 }
20120
20121 else
20122 goto done;
20123 }
20124 else
20125 clear_glyph_matrix (w->desired_matrix);
20126 }
20127
20128 try_to_scroll:
20129
20130
20131 if (!update_mode_line)
20132 {
20133 update_mode_line = true;
20134 w->update_mode_line = true;
20135 }
20136
20137
20138 if ((0 < scroll_conservatively
20139
20140
20141
20142
20143 || (scroll_minibuffer_conservatively && MINI_WINDOW_P (w))
20144 || 0 < emacs_scroll_step
20145 || temp_scroll_step
20146 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively))
20147 || NUMBERP (BVAR (current_buffer, scroll_down_aggressively)))
20148 && CHARPOS (startp) >= BEGV
20149 && CHARPOS (startp) <= ZV)
20150 {
20151
20152
20153 int ss = try_scrolling (window, just_this_one_p,
20154 ((scroll_minibuffer_conservatively
20155 && MINI_WINDOW_P (w))
20156 ? SCROLL_LIMIT + 1
20157 : scroll_conservatively),
20158 emacs_scroll_step,
20159 temp_scroll_step, last_line_misfit);
20160 switch (ss)
20161 {
20162 case SCROLLING_SUCCESS:
20163 goto done;
20164
20165 case SCROLLING_NEED_LARGER_MATRICES:
20166 goto need_larger_matrices;
20167
20168 case SCROLLING_FAILED:
20169 break;
20170
20171 default:
20172 emacs_abort ();
20173 }
20174 }
20175
20176
20177
20178
20179 recenter:
20180
20181 #ifdef GLYPH_DEBUG
20182 debug_method_add (w, "recenter");
20183 #endif
20184
20185
20186 if (!buffer_unchanged_p)
20187 w->base_line_number = 0;
20188
20189
20190 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20191 it.current_y = it.last_visible_y;
20192 if (centering_position < 0)
20193 {
20194 ptrdiff_t margin_pos = CHARPOS (startp);
20195 Lisp_Object aggressive;
20196 bool scrolling_up;
20197
20198
20199
20200 if (margin
20201
20202
20203
20204
20205
20206
20207 && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV)
20208 {
20209 struct it it1;
20210 void *it1data = NULL;
20211
20212 SAVE_IT (it1, it, it1data);
20213 start_display (&it1, w, startp);
20214 move_it_vertically (&it1, margin * frame_line_height);
20215 margin_pos = IT_CHARPOS (it1);
20216 RESTORE_IT (&it, &it, it1data);
20217 }
20218 scrolling_up = PT > margin_pos;
20219 aggressive =
20220 scrolling_up
20221 ? BVAR (current_buffer, scroll_up_aggressively)
20222 : BVAR (current_buffer, scroll_down_aggressively);
20223
20224 if (!MINI_WINDOW_P (w)
20225 && (scroll_conservatively > SCROLL_LIMIT || NUMBERP (aggressive)))
20226 {
20227 int pt_offset = 0;
20228
20229
20230
20231 if (!scroll_conservatively && NUMBERP (aggressive))
20232 {
20233 double float_amount = XFLOATINT (aggressive);
20234
20235 pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
20236 if (pt_offset == 0 && float_amount > 0)
20237 pt_offset = 1;
20238 if (pt_offset && margin > 0)
20239 margin -= 1;
20240 }
20241
20242
20243
20244 if (scrolling_up)
20245 {
20246 centering_position = it.last_visible_y;
20247 if (pt_offset)
20248 centering_position -= pt_offset;
20249 centering_position -=
20250 (frame_line_height * (1 + margin + last_line_misfit)
20251 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
20252
20253
20254 if (centering_position < margin * frame_line_height)
20255 centering_position = margin * frame_line_height;
20256 }
20257 else
20258 centering_position = margin * frame_line_height + pt_offset;
20259 }
20260 else
20261
20262
20263 centering_position = window_box_height (w) / 2;
20264 }
20265 if (current_buffer->long_line_optimizations_p
20266 && it.line_wrap == TRUNCATE)
20267 {
20268
20269
20270
20271 int nlines = centering_position / frame_line_height;
20272
20273 while (nlines-- && IT_CHARPOS (it) > BEGV)
20274 back_to_previous_visible_line_start (&it);
20275 reseat_1 (&it, it.current.pos, true);
20276 }
20277 else
20278 move_it_vertically_backward (&it, centering_position);
20279
20280 eassert (IT_CHARPOS (it) >= BEGV);
20281
20282
20283
20284
20285
20286
20287 if (it.current_y <= 0)
20288 {
20289 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20290 move_it_vertically_backward (&it, 0);
20291 it.current_y = 0;
20292 }
20293
20294 it.current_x = it.hpos = 0;
20295
20296
20297
20298
20299 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
20300
20301
20302 startp = run_window_scroll_functions (window, it.current.pos);
20303
20304
20305
20306
20307 itdata = bidi_shelve_cache ();
20308
20309
20310 use_desired_matrix = false;
20311 if (!current_matrix_up_to_date_p
20312 || windows_or_buffers_changed
20313 || f->cursor_type_changed
20314
20315
20316 || !NILP (Vwindow_scroll_functions)
20317 || !just_this_one_p
20318 || MINI_WINDOW_P (w)
20319 || !(used_current_matrix_p
20320 = try_window_reusing_current_matrix (w)))
20321 use_desired_matrix = (try_window (window, startp, 0) == 1);
20322
20323 bidi_unshelve_cache (itdata, false);
20324
20325
20326
20327
20328 if (f->fonts_changed)
20329 goto need_larger_matrices;
20330
20331
20332
20333
20334
20335
20336 if (w->cursor.vpos < 0)
20337 {
20338 if (w->window_end_valid && PT >= Z - w->window_end_pos)
20339 {
20340 clear_glyph_matrix (w->desired_matrix);
20341 move_it_by_lines (&it, 1);
20342 try_window (window, it.current.pos, 0);
20343 }
20344 else if (PT < IT_CHARPOS (it))
20345 {
20346 clear_glyph_matrix (w->desired_matrix);
20347 move_it_by_lines (&it, -1);
20348 try_window (window, it.current.pos, 0);
20349 }
20350 else if (scroll_conservatively > SCROLL_LIMIT
20351 && (it.method == GET_FROM_STRING
20352 || overlay_touches_p (IT_CHARPOS (it)))
20353 && IT_CHARPOS (it) < ZV)
20354 {
20355
20356
20357
20358
20359
20360
20361
20362
20363 ptrdiff_t pos0 = IT_CHARPOS (it);
20364
20365 clear_glyph_matrix (w->desired_matrix);
20366 do {
20367 move_it_by_lines (&it, 1);
20368 } while (IT_CHARPOS (it) == pos0);
20369 try_window (window, it.current.pos, 0);
20370 }
20371 else
20372 {
20373
20374 }
20375 }
20376
20377
20378
20379
20380
20381
20382 if (w->cursor.vpos < 0)
20383 {
20384
20385
20386
20387
20388 struct glyph_matrix *matrix =
20389 use_desired_matrix ? w->desired_matrix : w->current_matrix;
20390
20391 struct glyph_row *row =
20392 row_containing_pos (w, PT, matrix->rows, NULL, 0);
20393
20394
20395
20396
20397
20398
20399
20400 if (!row)
20401 {
20402 Lisp_Object val =
20403 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20404 Qnil, NULL);
20405
20406 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
20407 {
20408 ptrdiff_t alt_pos;
20409 Lisp_Object invis_end =
20410 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20411 Qnil, Qnil);
20412
20413 if (FIXNATP (invis_end))
20414 alt_pos = XFIXNAT (invis_end);
20415 else
20416 alt_pos = ZV;
20417 row = row_containing_pos (w, alt_pos, matrix->rows, NULL, 0);
20418 }
20419 }
20420
20421
20422
20423 if (!row)
20424 {
20425 row = matrix->rows;
20426
20427 if (row->tab_line_p)
20428 ++row;
20429 if (row->mode_line_p)
20430 ++row;
20431 }
20432 set_cursor_from_row (w, row, matrix, 0, 0, 0, 0);
20433 }
20434
20435 if (!cursor_row_fully_visible_p (w, false, false, false))
20436 {
20437
20438 if (w->vscroll)
20439 {
20440 w->vscroll = 0;
20441 clear_glyph_matrix (w->desired_matrix);
20442 goto recenter;
20443 }
20444
20445
20446
20447
20448
20449 if (scroll_conservatively > SCROLL_LIMIT)
20450 {
20451 int window_total_lines
20452 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
20453 bool move_down = w->cursor.vpos >= window_total_lines / 2;
20454
20455 move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
20456 clear_glyph_matrix (w->desired_matrix);
20457 if (1 == try_window (window, it.current.pos,
20458 TRY_WINDOW_CHECK_MARGINS))
20459 goto done;
20460 }
20461
20462
20463
20464
20465 if (centering_position == 0)
20466 goto done;
20467
20468 clear_glyph_matrix (w->desired_matrix);
20469 centering_position = 0;
20470 goto recenter;
20471 }
20472
20473 done:
20474
20475 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20476 w->start_at_line_beg = (CHARPOS (startp) == BEGV
20477 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
20478
20479
20480 if ((update_mode_line
20481
20482
20483
20484
20485 || (!just_this_one_p
20486 && !FRAME_WINDOW_P (f)
20487 && !WINDOW_FULL_WIDTH_P (w))
20488
20489 || w->base_line_pos > 0
20490
20491 || (w->column_number_displayed != -1
20492 && (w->column_number_displayed != current_column ())))
20493
20494 && (window_wants_mode_line (w)
20495 || window_wants_header_line (w)
20496 || window_wants_tab_line (w)))
20497 {
20498 specpdl_ref count1 = SPECPDL_INDEX ();
20499
20500 specbind (Qinhibit_quit, Qt);
20501 display_mode_lines (w);
20502 unbind_to (count1, Qnil);
20503
20504
20505
20506 if (window_wants_mode_line (w)
20507 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
20508 {
20509 f->fonts_changed = true;
20510 w->mode_line_height = -1;
20511 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
20512 = DESIRED_MODE_LINE_HEIGHT (w);
20513 }
20514
20515
20516
20517 if (window_wants_tab_line (w)
20518 && CURRENT_TAB_LINE_HEIGHT (w) != DESIRED_TAB_LINE_HEIGHT (w))
20519 {
20520 f->fonts_changed = true;
20521 w->tab_line_height = -1;
20522 MATRIX_TAB_LINE_ROW (w->current_matrix)->height
20523 = DESIRED_TAB_LINE_HEIGHT (w);
20524 }
20525
20526
20527
20528 if (window_wants_header_line (w)
20529 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
20530 {
20531 f->fonts_changed = true;
20532 w->header_line_height = -1;
20533 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
20534 = DESIRED_HEADER_LINE_HEIGHT (w);
20535 }
20536
20537 if (f->fonts_changed)
20538 goto need_larger_matrices;
20539 }
20540
20541 if (!line_number_displayed && w->base_line_pos != -1)
20542 {
20543 w->base_line_pos = 0;
20544 w->base_line_number = 0;
20545 }
20546
20547 finish_menu_bars:
20548
20549
20550
20551 if (update_mode_line
20552 && EQ (FRAME_SELECTED_WINDOW (f), window))
20553 {
20554 bool redisplay_menu_p;
20555
20556 if (FRAME_WINDOW_P (f))
20557 {
20558 #ifdef HAVE_EXT_MENU_BAR
20559 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
20560 #else
20561 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20562 #endif
20563 }
20564 else
20565 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20566
20567 if (redisplay_menu_p)
20568 display_menu_bar (w);
20569
20570 #ifdef HAVE_WINDOW_SYSTEM
20571 if (FRAME_WINDOW_P (f))
20572 {
20573 if (WINDOWP (f->tab_bar_window)
20574 && (FRAME_TAB_BAR_LINES (f) > 0
20575 || !NILP (Vauto_resize_tab_bars))
20576 && redisplay_tab_bar (f))
20577 ignore_mouse_drag_p = true;
20578
20579 #ifdef HAVE_EXT_TOOL_BAR
20580 if (FRAME_EXTERNAL_TOOL_BAR (f))
20581 update_frame_tool_bar (f);
20582 #else
20583 if (WINDOWP (f->tool_bar_window)
20584 && (FRAME_TOOL_BAR_LINES (f) > 0
20585 || !NILP (Vauto_resize_tool_bars))
20586 && redisplay_tool_bar (f))
20587 ignore_mouse_drag_p = true;
20588 #endif
20589 }
20590 else
20591 {
20592 if ((FRAME_TAB_BAR_LINES (f) > 0))
20593 display_tab_bar (w);
20594 }
20595
20596 gui_consider_frame_title (w->frame);
20597 #else
20598 if ((FRAME_TAB_BAR_LINES (f) > 0))
20599 display_tab_bar (w);
20600 #endif
20601 }
20602
20603 #ifdef HAVE_WINDOW_SYSTEM
20604 if (FRAME_WINDOW_P (f)
20605 && update_window_fringes (w, (just_this_one_p
20606 || (!used_current_matrix_p && !overlay_arrow_seen)
20607 || w->pseudo_window_p)))
20608 {
20609 update_begin (f);
20610 block_input ();
20611 if (draw_window_fringes (w, true))
20612 {
20613 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
20614 gui_draw_right_divider (w);
20615 else
20616 gui_draw_vertical_border (w);
20617 }
20618 unblock_input ();
20619 update_end (f);
20620 }
20621
20622 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
20623 gui_draw_bottom_divider (w);
20624 #endif
20625
20626
20627
20628
20629
20630 need_larger_matrices:
20631 ;
20632 finish_scroll_bars:
20633
20634 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20635 {
20636 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
20637
20638 set_vertical_scroll_bar (w);
20639
20640 if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20641
20642 set_horizontal_scroll_bar (w);
20643
20644
20645
20646 if (FRAME_TERMINAL (f)->redeem_scroll_bar_hook)
20647 (*FRAME_TERMINAL (f)->redeem_scroll_bar_hook) (w);
20648 }
20649
20650
20651
20652
20653 if (CHARPOS (opoint) < BEGV)
20654 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
20655 else if (CHARPOS (opoint) > ZV)
20656 TEMP_SET_PT_BOTH (Z, Z_BYTE);
20657 else
20658 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
20659
20660 set_buffer_internal_1 (old);
20661
20662
20663 if (CHARPOS (lpoint) <= ZV)
20664 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
20665
20666 unbind_to (count, Qnil);
20667 }
20668
20669
20670
20671
20672
20673
20674
20675
20676
20677
20678
20679
20680
20681
20682
20683
20684
20685
20686
20687
20688 int
20689 try_window (Lisp_Object window, struct text_pos pos, int flags)
20690 {
20691 struct window *w = XWINDOW (window);
20692 struct it it;
20693 struct glyph_row *last_text_row = NULL;
20694 struct frame *f = XFRAME (w->frame);
20695 int cursor_vpos = w->cursor.vpos;
20696
20697
20698 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
20699
20700
20701 w->cursor.vpos = -1;
20702 overlay_arrow_seen = false;
20703
20704
20705 start_display (&it, w, pos);
20706 it.glyph_row->reversed_p = false;
20707
20708
20709 while (it.current_y < it.last_visible_y)
20710 {
20711 int last_row_scale = it.w->nrows_scale_factor;
20712 int last_col_scale = it.w->ncols_scale_factor;
20713 if (display_line (&it, cursor_vpos))
20714 last_text_row = it.glyph_row - 1;
20715 if (f->fonts_changed
20716 && !((flags & TRY_WINDOW_IGNORE_FONTS_CHANGE)
20717
20718
20719 && last_row_scale == it.w->nrows_scale_factor
20720 && last_col_scale == it.w->ncols_scale_factor))
20721 return 0;
20722 }
20723
20724
20725
20726 ptrdiff_t it_charpos = IT_CHARPOS (it);
20727
20728
20729
20730
20731 if ((flags & TRY_WINDOW_CHECK_MARGINS)
20732 && w->vscroll == 0
20733 && !MINI_WINDOW_P (w))
20734 {
20735 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
20736 int bot_scroll_margin = top_scroll_margin;
20737 if (window_wants_header_line (w))
20738 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
20739 if (window_wants_tab_line (w))
20740 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
20741 start_display (&it, w, pos);
20742
20743 if ((w->cursor.y >= 0
20744 && w->cursor.y < top_scroll_margin
20745 && CHARPOS (pos) > BEGV)
20746
20747
20748
20749
20750 || w->cursor.y > (it.last_visible_y - partial_line_height (&it)
20751 - bot_scroll_margin - 1))
20752 {
20753 w->cursor.vpos = -1;
20754 clear_glyph_matrix (w->desired_matrix);
20755 return -1;
20756 }
20757 }
20758
20759
20760 if (w->window_end_pos <= 0 && Z != it_charpos)
20761 w->update_mode_line = true;
20762
20763
20764
20765
20766 if (last_text_row)
20767 {
20768 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
20769 adjust_window_ends (w, last_text_row, false);
20770 eassert
20771 (MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->desired_matrix,
20772 w->window_end_vpos)));
20773 }
20774 else
20775 {
20776 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
20777 w->window_end_pos = Z - ZV;
20778 w->window_end_vpos = 0;
20779 }
20780
20781
20782 w->window_end_valid = false;
20783 return 1;
20784 }
20785
20786
20787
20788
20789
20790
20791
20792
20793
20794
20795
20796
20797 static bool
20798 try_window_reusing_current_matrix (struct window *w)
20799 {
20800 struct frame *f = XFRAME (w->frame);
20801 struct glyph_row *bottom_row;
20802 struct it it;
20803 struct run run;
20804 struct text_pos start, new_start;
20805 int nrows_scrolled, i;
20806 struct glyph_row *last_text_row;
20807 struct glyph_row *last_reused_text_row;
20808 struct glyph_row *start_row;
20809 int start_vpos, min_y, max_y;
20810
20811 #ifdef GLYPH_DEBUG
20812 if (inhibit_try_window_reusing)
20813 return false;
20814 #endif
20815
20816 if (
20817 !FRAME_WINDOW_P (f)
20818
20819
20820 || windows_or_buffers_changed
20821 || f->cursor_type_changed
20822
20823
20824
20825 || overlay_arrow_in_current_buffer_p ())
20826 return false;
20827
20828
20829 if (!NILP (Vshow_trailing_whitespace))
20830 return false;
20831
20832
20833 if (window_wants_tab_line (w)
20834 != MATRIX_TAB_LINE_ROW (w->current_matrix)->mode_line_p)
20835 return false;
20836
20837
20838 if (window_wants_header_line (w)
20839 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
20840 return false;
20841
20842
20843
20844 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
20845 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row))
20846 return false;
20847
20848
20849 clear_glyph_matrix (w->desired_matrix);
20850
20851
20852
20853
20854 if (!NILP (Vdisplay_line_numbers))
20855 return false;
20856
20857
20858
20859
20860 #ifdef HAVE_NTGUI
20861 if (w32_use_visible_system_caret)
20862 return false;
20863 #endif
20864
20865
20866
20867 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
20868 start = start_row->minpos;
20869 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
20870
20871 if (CHARPOS (new_start) <= CHARPOS (start))
20872 {
20873
20874
20875
20876
20877 if (in_ellipses_for_invisible_text_p (&start_row->start, w))
20878 return false;
20879
20880 IF_DEBUG (debug_method_add (w, "twu1"));
20881
20882
20883
20884
20885
20886 start_display (&it, w, new_start);
20887 w->cursor.vpos = -1;
20888 last_text_row = last_reused_text_row = NULL;
20889
20890 while (it.current_y < it.last_visible_y && !f->fonts_changed)
20891 {
20892
20893
20894
20895
20896 while (IT_CHARPOS (it) > CHARPOS (start))
20897 {
20898
20899 start_row++;
20900 start = start_row->minpos;
20901
20902 if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
20903 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
20904 || CHARPOS (start) == ZV)
20905 {
20906 clear_glyph_matrix (w->desired_matrix);
20907 return false;
20908 }
20909
20910 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
20911 }
20912
20913
20914 if (IT_CHARPOS (it) == CHARPOS (start)
20915
20916
20917
20918
20919
20920 && it.current.dpvec_index < 0)
20921 break;
20922
20923 it.glyph_row->reversed_p = false;
20924 if (display_line (&it, -1))
20925 last_text_row = it.glyph_row - 1;
20926
20927 }
20928
20929
20930
20931
20932 if (it.current_y < it.last_visible_y)
20933 {
20934 struct glyph_row *row;
20935
20936
20937 nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix));
20938
20939
20940 if (w->cursor.vpos < 0)
20941 {
20942 int dy = it.current_y - start_row->y;
20943
20944 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
20945 row = row_containing_pos (w, PT, row, NULL, dy);
20946 if (row)
20947 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
20948 dy, nrows_scrolled);
20949 else
20950 {
20951 clear_glyph_matrix (w->desired_matrix);
20952 return false;
20953 }
20954 }
20955
20956
20957
20958
20959
20960
20961
20962 run.current_y = start_row->y;
20963 run.desired_y = it.current_y;
20964 run.height = it.last_visible_y - it.current_y;
20965
20966 if (run.height > 0 && run.current_y != run.desired_y)
20967 {
20968 #ifdef HAVE_WINDOW_SYSTEM
20969 update_begin (f);
20970 gui_update_window_begin (w);
20971 FRAME_RIF (f)->clear_window_mouse_face (w);
20972 FRAME_RIF (f)->scroll_run_hook (w, &run);
20973 gui_update_window_end (w, false, false);
20974 update_end (f);
20975 #endif
20976 }
20977
20978
20979 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
20980 rotate_matrix (w->current_matrix,
20981 start_vpos,
20982 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
20983 nrows_scrolled);
20984
20985
20986 for (i = 0; i < nrows_scrolled; ++i)
20987 (start_row + i)->enabled_p = false;
20988
20989
20990 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
20991 max_y = it.last_visible_y;
20992 for (row = start_row + nrows_scrolled;
20993 row < bottom_row;
20994 ++row)
20995 {
20996 row->y = it.current_y;
20997 row->visible_height = row->height;
20998
20999 if (row->y < min_y)
21000 row->visible_height -= min_y - row->y;
21001 if (row->y + row->height > max_y)
21002 row->visible_height -= row->y + row->height - max_y;
21003 if (row->fringe_bitmap_periodic_p)
21004 row->redraw_fringe_bitmaps_p = true;
21005
21006 it.current_y += row->height;
21007
21008 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21009 last_reused_text_row = row;
21010 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
21011 break;
21012 }
21013
21014
21015
21016 for (++row; row < bottom_row; ++row)
21017 row->enabled_p = row->mode_line_p = row->tab_line_p = false;
21018 }
21019
21020
21021
21022
21023
21024 if (last_reused_text_row)
21025 adjust_window_ends (w, last_reused_text_row, true);
21026 else if (last_text_row)
21027 adjust_window_ends (w, last_text_row, false);
21028 else
21029 {
21030
21031 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
21032 w->window_end_pos = Z - ZV;
21033 w->window_end_vpos = 0;
21034 }
21035 w->window_end_valid = false;
21036
21037
21038 w->desired_matrix->no_scrolling_p = true;
21039
21040 #ifdef GLYPH_DEBUG
21041 debug_method_add (w, "try_window_reusing_current_matrix 1");
21042 #endif
21043 return true;
21044 }
21045 else if (CHARPOS (new_start) > CHARPOS (start))
21046 {
21047 struct glyph_row *pt_row, *row;
21048 struct glyph_row *first_reusable_row;
21049 struct glyph_row *first_row_to_display;
21050 int dy;
21051 int yb = window_text_bottom_y (w);
21052
21053
21054
21055 first_reusable_row = start_row;
21056 while (first_reusable_row->enabled_p
21057 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
21058 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21059 < CHARPOS (new_start)))
21060 ++first_reusable_row;
21061
21062
21063 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
21064 || !first_reusable_row->enabled_p
21065 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21066 != CHARPOS (new_start)))
21067 return false;
21068
21069
21070
21071
21072
21073 pt_row = NULL;
21074 for (first_row_to_display = first_reusable_row;
21075 MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
21076 ++first_row_to_display)
21077 {
21078 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
21079 && (PT < MATRIX_ROW_END_CHARPOS (first_row_to_display)
21080 || (PT == MATRIX_ROW_END_CHARPOS (first_row_to_display)
21081 && first_row_to_display->ends_at_zv_p
21082 && pt_row == NULL)))
21083 pt_row = first_row_to_display;
21084 }
21085
21086 if (first_row_to_display->y >= yb)
21087 return false;
21088
21089
21090 init_to_row_start (&it, w, first_row_to_display);
21091
21092 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
21093 - start_vpos);
21094 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
21095 - nrows_scrolled);
21096 it.current_y = (first_row_to_display->y - first_reusable_row->y
21097 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
21098
21099
21100
21101
21102 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
21103 if (pt_row == NULL)
21104 w->cursor.vpos = -1;
21105 last_text_row = NULL;
21106 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21107 if (display_line (&it, w->cursor.vpos))
21108 last_text_row = it.glyph_row - 1;
21109
21110
21111
21112 if (pt_row)
21113 {
21114 w->cursor.vpos -= nrows_scrolled;
21115 w->cursor.y -= first_reusable_row->y - start_row->y;
21116 }
21117
21118
21119
21120
21121
21122 if (w->cursor.vpos < 0)
21123 {
21124 clear_glyph_matrix (w->desired_matrix);
21125 return false;
21126 }
21127
21128
21129 run.current_y = first_reusable_row->y;
21130 run.desired_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21131 run.height = it.last_visible_y - run.current_y;
21132 dy = run.current_y - run.desired_y;
21133
21134 if (run.height)
21135 {
21136 #ifdef HAVE_WINDOW_SYSTEM
21137 update_begin (f);
21138 gui_update_window_begin (w);
21139 FRAME_RIF (f)->clear_window_mouse_face (w);
21140 FRAME_RIF (f)->scroll_run_hook (w, &run);
21141 gui_update_window_end (w, false, false);
21142 update_end (f);
21143 #endif
21144 }
21145
21146
21147 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21148 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21149 max_y = it.last_visible_y;
21150 for (row = first_reusable_row; row < first_row_to_display; ++row)
21151 {
21152 row->y -= dy;
21153 row->visible_height = row->height;
21154 if (row->y < min_y)
21155 row->visible_height -= min_y - row->y;
21156 if (row->y + row->height > max_y)
21157 row->visible_height -= row->y + row->height - max_y;
21158 if (row->fringe_bitmap_periodic_p)
21159 row->redraw_fringe_bitmaps_p = true;
21160 }
21161
21162
21163 eassert (nrows_scrolled > 0);
21164 rotate_matrix (w->current_matrix,
21165 start_vpos,
21166 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21167 -nrows_scrolled);
21168
21169
21170 for (row -= nrows_scrolled; row < bottom_row; ++row)
21171 row->enabled_p = false;
21172
21173
21174
21175 if (pt_row)
21176 {
21177 for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
21178 row < bottom_row
21179 && PT >= MATRIX_ROW_END_CHARPOS (row)
21180 && !row->ends_at_zv_p;
21181 row++)
21182 {
21183 w->cursor.vpos++;
21184 w->cursor.y = row->y;
21185 }
21186 if (row < bottom_row)
21187 {
21188
21189
21190
21191
21192 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
21193 {
21194 if (!set_cursor_from_row (w, row, w->current_matrix,
21195 0, 0, 0, 0))
21196 {
21197 clear_glyph_matrix (w->desired_matrix);
21198 return false;
21199 }
21200 }
21201 else
21202 {
21203 struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
21204 struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21205
21206 for (; glyph < end
21207 && (!BUFFERP (glyph->object)
21208 || glyph->charpos < PT);
21209 glyph++)
21210 {
21211 w->cursor.hpos++;
21212 w->cursor.x += glyph->pixel_width;
21213 }
21214 }
21215 }
21216 }
21217
21218
21219
21220
21221 if (last_text_row)
21222 adjust_window_ends (w, last_text_row, false);
21223 else
21224 w->window_end_vpos -= nrows_scrolled;
21225
21226 w->window_end_valid = false;
21227 w->desired_matrix->no_scrolling_p = true;
21228
21229 #ifdef GLYPH_DEBUG
21230 debug_method_add (w, "try_window_reusing_current_matrix 2");
21231 #endif
21232 return true;
21233 }
21234
21235 return false;
21236 }
21237
21238
21239
21240
21241
21242
21243
21244 static struct glyph_row *find_last_unchanged_at_beg_row (struct window *);
21245 static struct glyph_row *find_first_unchanged_at_end_row (struct window *,
21246 ptrdiff_t *, ptrdiff_t *);
21247 static struct glyph_row *
21248 find_last_row_displaying_text (struct glyph_matrix *, struct it *,
21249 struct glyph_row *);
21250
21251
21252
21253
21254
21255
21256
21257 static struct glyph_row *
21258 find_last_row_displaying_text (struct glyph_matrix *matrix, struct it *it,
21259 struct glyph_row *start)
21260 {
21261 struct glyph_row *row, *row_found;
21262
21263
21264
21265
21266 row_found = NULL;
21267 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
21268 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21269 {
21270 eassert (row->enabled_p);
21271 row_found = row;
21272 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
21273 break;
21274 ++row;
21275 }
21276
21277 return row_found;
21278 }
21279
21280
21281
21282
21283
21284
21285
21286
21287
21288
21289
21290
21291 static struct glyph_row *
21292 find_last_unchanged_at_beg_row (struct window *w)
21293 {
21294 ptrdiff_t first_changed_pos = BEG + BEG_UNCHANGED;
21295 struct glyph_row *row;
21296 struct glyph_row *row_found = NULL;
21297 int yb = window_text_bottom_y (w);
21298
21299
21300 for (row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21301 MATRIX_ROW_DISPLAYS_TEXT_P (row)
21302 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos;
21303 ++row)
21304 {
21305 if (
21306
21307 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
21308
21309
21310 && !row->ends_at_zv_p
21311
21312
21313
21314 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
21315 && (row->continued_p
21316 || row->exact_window_width_line_p))
21317
21318
21319
21320
21321
21322
21323
21324 && CHARPOS (row->end.pos) <= ZV)
21325 row_found = row;
21326
21327
21328 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
21329 break;
21330 }
21331
21332 return row_found;
21333 }
21334
21335
21336
21337
21338
21339
21340
21341
21342
21343
21344
21345
21346
21347
21348 static struct glyph_row *
21349 find_first_unchanged_at_end_row (struct window *w,
21350 ptrdiff_t *delta, ptrdiff_t *delta_bytes)
21351 {
21352 struct glyph_row *row;
21353 struct glyph_row *row_found = NULL;
21354
21355 *delta = *delta_bytes = 0;
21356
21357
21358
21359 eassert (w->window_end_valid);
21360
21361
21362
21363
21364 if (w->window_end_pos >= END_UNCHANGED)
21365 return NULL;
21366
21367
21368 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21369
21370
21371 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21372 {
21373
21374
21375
21376
21377
21378 ptrdiff_t Z_old =
21379 MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21380 ptrdiff_t Z_BYTE_old =
21381 MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21382 ptrdiff_t last_unchanged_pos, last_unchanged_pos_old;
21383 struct glyph_row *first_text_row
21384 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21385
21386 *delta = Z - Z_old;
21387 *delta_bytes = Z_BYTE - Z_BYTE_old;
21388
21389
21390
21391
21392
21393
21394
21395 last_unchanged_pos = Z - END_UNCHANGED + BEG;
21396 last_unchanged_pos_old = last_unchanged_pos - *delta;
21397
21398
21399
21400 for (; row > first_text_row; --row)
21401 {
21402
21403
21404 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
21405 break;
21406
21407 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
21408 row_found = row;
21409 }
21410 }
21411
21412 eassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
21413
21414 return row_found;
21415 }
21416
21417
21418
21419
21420
21421
21422
21423
21424 static void
21425 sync_frame_with_window_matrix_rows (struct window *w)
21426 {
21427 struct frame *f = XFRAME (w->frame);
21428 struct glyph_row *window_row, *window_row_end, *frame_row;
21429
21430
21431
21432 eassert (BUFFERP (w->contents));
21433 eassert (WINDOW_FULL_WIDTH_P (w));
21434 eassert (!FRAME_WINDOW_P (f));
21435
21436
21437
21438
21439
21440 window_row = w->current_matrix->rows;
21441 window_row_end = window_row + w->current_matrix->nrows;
21442 frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
21443 while (window_row < window_row_end)
21444 {
21445 struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
21446 struct glyph *end = window_row->glyphs[LAST_AREA];
21447
21448 frame_row->glyphs[LEFT_MARGIN_AREA] = start;
21449 frame_row->glyphs[TEXT_AREA] = start;
21450 frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
21451 frame_row->glyphs[LAST_AREA] = end;
21452
21453
21454
21455 if (!window_row->enabled_p)
21456 frame_row->enabled_p = false;
21457
21458 ++window_row, ++frame_row;
21459 }
21460 }
21461
21462
21463
21464
21465
21466
21467
21468 struct glyph_row *
21469 row_containing_pos (struct window *w, ptrdiff_t charpos,
21470 struct glyph_row *start, struct glyph_row *end, int dy)
21471 {
21472 struct glyph_row *row = start;
21473 struct glyph_row *best_row = NULL;
21474 ptrdiff_t mindif = BUF_ZV (XBUFFER (w->contents)) + 1;
21475 int last_y;
21476
21477
21478 if (row->tab_line_p)
21479 ++row;
21480 if (row->mode_line_p)
21481 ++row;
21482
21483 if ((end && row >= end) || !row->enabled_p)
21484 return NULL;
21485
21486 last_y = window_text_bottom_y (w) - dy;
21487
21488 while (true)
21489 {
21490
21491 if ((end && row >= end) || !row->enabled_p)
21492 return NULL;
21493
21494
21495
21496 if (MATRIX_ROW_BOTTOM_Y (row) > last_y)
21497 return NULL;
21498
21499
21500 if (! (MATRIX_ROW_END_CHARPOS (row) < charpos
21501 || (MATRIX_ROW_END_CHARPOS (row) == charpos
21502
21503
21504
21505
21506 && !row_for_charpos_p (row, charpos)))
21507 && charpos >= MATRIX_ROW_START_CHARPOS (row))
21508 {
21509 struct glyph *g;
21510
21511 if (NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21512 || (!best_row && !row->continued_p))
21513 return row;
21514
21515
21516
21517
21518 for (g = row->glyphs[TEXT_AREA];
21519 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21520 g++)
21521 {
21522 if (!STRINGP (g->object))
21523 {
21524 if (g->charpos > 0 && eabs (g->charpos - charpos) < mindif)
21525 {
21526 mindif = eabs (g->charpos - charpos);
21527 best_row = row;
21528
21529 if (mindif == 0)
21530 return best_row;
21531 }
21532 }
21533 }
21534 }
21535 else if (best_row && !row->continued_p)
21536 return best_row;
21537 ++row;
21538 }
21539 }
21540
21541
21542
21543
21544
21545
21546
21547
21548
21549
21550
21551
21552
21553
21554
21555
21556
21557
21558
21559
21560
21561
21562
21563
21564
21565
21566
21567
21568
21569
21570
21571
21572
21573
21574
21575
21576
21577
21578
21579
21580
21581
21582
21583
21584 static int
21585 try_window_id (struct window *w)
21586 {
21587 struct frame *f = XFRAME (w->frame);
21588 struct glyph_matrix *current_matrix = w->current_matrix;
21589 struct glyph_matrix *desired_matrix = w->desired_matrix;
21590 struct glyph_row *last_unchanged_at_beg_row;
21591 struct glyph_row *first_unchanged_at_end_row;
21592 struct glyph_row *row;
21593 struct glyph_row *bottom_row;
21594 int bottom_vpos;
21595 struct it it;
21596 ptrdiff_t delta = 0, delta_bytes = 0, stop_pos;
21597 int dvpos, dy;
21598 struct text_pos start_pos;
21599 struct run run;
21600 int first_unchanged_at_end_vpos = 0;
21601 struct glyph_row *last_text_row, *last_text_row_at_end;
21602 struct text_pos start;
21603 ptrdiff_t first_changed_charpos, last_changed_charpos;
21604
21605 #ifdef GLYPH_DEBUG
21606 if (inhibit_try_window_id)
21607 return 0;
21608 #endif
21609
21610
21611 #if false
21612 #define GIVE_UP(X) \
21613 do { \
21614 redisplay_trace ("try_window_id give up %d\n", X); \
21615 return 0; \
21616 } while (false)
21617 #else
21618 #define GIVE_UP(X) return 0
21619 #endif
21620
21621 SET_TEXT_POS_FROM_MARKER (start, w->start);
21622
21623
21624
21625 if (MINI_WINDOW_P (w))
21626 GIVE_UP (1);
21627
21628
21629 if (windows_or_buffers_changed || f->cursor_type_changed)
21630 GIVE_UP (2);
21631
21632
21633
21634
21635 if (w->last_overlay_modified != OVERLAY_MODIFF)
21636 GIVE_UP (200);
21637
21638
21639
21640
21641
21642 if (current_buffer->clip_changed
21643 || current_buffer->prevent_redisplay_optimizations_p)
21644 GIVE_UP (3);
21645
21646
21647 if (!FRAME_WINDOW_P (f)
21648 && (!FRAME_LINE_INS_DEL_OK (f)
21649 || !WINDOW_FULL_WIDTH_P (w)))
21650 GIVE_UP (4);
21651
21652
21653 if (PT < CHARPOS (start))
21654 GIVE_UP (5);
21655
21656
21657 if (w->last_modified == 0)
21658 GIVE_UP (6);
21659
21660
21661 if (w->hscroll != 0)
21662 GIVE_UP (7);
21663
21664
21665 if (!w->window_end_valid)
21666 GIVE_UP (8);
21667
21668
21669 if (!NILP (Vshow_trailing_whitespace))
21670 GIVE_UP (11);
21671
21672
21673
21674 if (overlay_arrows_changed_p (false))
21675 GIVE_UP (12);
21676
21677
21678
21679
21680
21681 if (!NILP (BVAR (XBUFFER (w->contents), word_wrap)))
21682 GIVE_UP (21);
21683
21684
21685
21686
21687
21688
21689
21690
21691
21692 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21693 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
21694 GIVE_UP (22);
21695
21696
21697
21698 if (!NILP (BVAR (XBUFFER (w->contents), extra_line_spacing)))
21699 GIVE_UP (23);
21700
21701
21702
21703 if (EQ (Vdisplay_line_numbers, Qrelative)
21704 || EQ (Vdisplay_line_numbers, Qvisual)
21705 || (!NILP (Vdisplay_line_numbers)
21706 && NILP (Finternal_lisp_face_equal_p (Qline_number,
21707 Qline_number_current_line,
21708 w->frame))))
21709 GIVE_UP (24);
21710
21711
21712
21713
21714 if (composition_break_at_point)
21715 GIVE_UP (27);
21716
21717
21718
21719
21720
21721 if (MODIFF > SAVE_MODIFF
21722
21723 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
21724 {
21725 if (GPT - BEG < BEG_UNCHANGED)
21726 BEG_UNCHANGED = GPT - BEG;
21727 if (Z - GPT < END_UNCHANGED)
21728 END_UNCHANGED = Z - GPT;
21729 }
21730
21731
21732 first_changed_charpos = BEG + BEG_UNCHANGED;
21733 last_changed_charpos = Z - END_UNCHANGED;
21734
21735
21736
21737
21738
21739
21740 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21741 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
21742 && ((last_changed_charpos < CHARPOS (start)
21743 && CHARPOS (start) == BEGV)
21744 || (last_changed_charpos < CHARPOS (start) - 1
21745 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
21746 {
21747 ptrdiff_t Z_old, Z_delta, Z_BYTE_old, Z_delta_bytes;
21748 struct glyph_row *r0;
21749
21750
21751
21752 Z_old = MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21753 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21754 Z_delta = Z - Z_old;
21755 Z_delta_bytes = Z_BYTE - Z_BYTE_old;
21756
21757
21758
21759
21760 if (PT >= MATRIX_ROW_END_CHARPOS (row) + Z_delta)
21761 GIVE_UP (13);
21762
21763
21764
21765
21766 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21767 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + Z_delta
21768 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + Z_delta_bytes
21769
21770 && !(PT >= MATRIX_ROW_START_CHARPOS (row) + Z_delta
21771 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21772 {
21773
21774 if (Z_delta || Z_delta_bytes)
21775 {
21776 struct glyph_row *r1
21777 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
21778 increment_matrix_positions (w->current_matrix,
21779 MATRIX_ROW_VPOS (r0, current_matrix),
21780 MATRIX_ROW_VPOS (r1, current_matrix),
21781 Z_delta, Z_delta_bytes);
21782 }
21783
21784
21785 row = row_containing_pos (w, PT, r0, NULL, 0);
21786 if (row)
21787 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
21788 return 1;
21789 }
21790 }
21791
21792
21793
21794
21795
21796 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
21797
21798
21799 && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
21800 || first_changed_charpos == last_changed_charpos))
21801 {
21802 struct glyph_row *r0;
21803
21804
21805
21806
21807 if (PT >= MATRIX_ROW_END_CHARPOS (row))
21808 GIVE_UP (14);
21809
21810
21811
21812
21813 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21814 if (TEXT_POS_EQUAL_P (start, r0->minpos)
21815
21816 && !(PT >= MATRIX_ROW_START_CHARPOS (row)
21817 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21818 {
21819
21820
21821 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
21822 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
21823
21824
21825 row = row_containing_pos (w, PT, r0, NULL, 0);
21826 if (row)
21827 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
21828 return 2;
21829 }
21830 }
21831
21832
21833
21834
21835
21836
21837
21838
21839 if (CHARPOS (start) >= first_changed_charpos
21840 && CHARPOS (start) <= last_changed_charpos)
21841 GIVE_UP (15);
21842
21843
21844
21845
21846
21847 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
21848 if (!TEXT_POS_EQUAL_P (start, row->minpos))
21849 GIVE_UP (16);
21850
21851
21852
21853 row = MATRIX_ROW (current_matrix, w->window_end_vpos);
21854 if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
21855 GIVE_UP (20);
21856
21857
21858
21859
21860
21861 #ifdef HAVE_NTGUI
21862 if (FRAME_W32_P (f) && w32_use_visible_system_caret)
21863 GIVE_UP (25);
21864 #endif
21865
21866
21867
21868
21869
21870
21871
21872 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
21873 if (last_unchanged_at_beg_row)
21874 {
21875
21876
21877
21878
21879 while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
21880 || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
21881 && last_unchanged_at_beg_row > w->current_matrix->rows)
21882 --last_unchanged_at_beg_row;
21883
21884 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
21885 GIVE_UP (17);
21886
21887 if (! init_to_row_end (&it, w, last_unchanged_at_beg_row))
21888 GIVE_UP (18);
21889
21890
21891
21892 if (it.sp > 1
21893 && it.method == GET_FROM_IMAGE && it.image_id == -1)
21894 GIVE_UP (26);
21895 start_pos = it.current.pos;
21896
21897
21898
21899
21900 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
21901 current_matrix);
21902 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
21903 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
21904
21905 eassert (it.hpos == 0 && it.current_x == 0);
21906 }
21907 else
21908 {
21909
21910
21911 start_display (&it, w, start);
21912 it.vpos = it.first_vpos;
21913 start_pos = it.current.pos;
21914 }
21915
21916
21917
21918
21919
21920
21921
21922 first_unchanged_at_end_row
21923 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
21924 IF_DEBUG (debug_delta = delta);
21925 IF_DEBUG (debug_delta_bytes = delta_bytes);
21926
21927
21928
21929
21930
21931
21932 stop_pos = 0;
21933 if (first_unchanged_at_end_row)
21934 {
21935 eassert (last_unchanged_at_beg_row == NULL
21936 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
21937
21938
21939
21940
21941
21942 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
21943 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
21944 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
21945 < it.last_visible_y))
21946 ++first_unchanged_at_end_row;
21947
21948 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
21949 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
21950 >= it.last_visible_y))
21951 first_unchanged_at_end_row = NULL;
21952 else
21953 {
21954 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
21955 + delta);
21956 first_unchanged_at_end_vpos
21957 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
21958 eassert (stop_pos >= Z - END_UNCHANGED);
21959 }
21960 }
21961 else if (last_unchanged_at_beg_row == NULL)
21962 GIVE_UP (19);
21963
21964
21965 #ifdef GLYPH_DEBUG
21966
21967
21968
21969
21970 eassert (first_unchanged_at_end_row == NULL
21971 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
21972
21973 debug_last_unchanged_at_beg_vpos
21974 = (last_unchanged_at_beg_row
21975 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
21976 : -1);
21977 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
21978
21979 #endif
21980
21981
21982
21983
21984
21985 w->cursor.vpos = -1;
21986 last_text_row = NULL;
21987 overlay_arrow_seen = false;
21988 if (it.current_y < it.last_visible_y
21989 && !f->fonts_changed
21990 && (first_unchanged_at_end_row == NULL
21991 || IT_CHARPOS (it) < stop_pos))
21992 it.glyph_row->reversed_p = false;
21993 while (it.current_y < it.last_visible_y
21994 && !f->fonts_changed
21995 && (first_unchanged_at_end_row == NULL
21996 || IT_CHARPOS (it) < stop_pos))
21997 {
21998 if (display_line (&it, -1))
21999 last_text_row = it.glyph_row - 1;
22000 }
22001
22002 if (f->fonts_changed)
22003 return -1;
22004
22005
22006
22007
22008
22009
22010
22011
22012
22013
22014
22015 if (!w->window_end_valid)
22016 {
22017 clear_glyph_matrix (w->desired_matrix);
22018 return -1;
22019 }
22020
22021
22022
22023
22024 if (first_unchanged_at_end_row
22025
22026
22027 && it.current_y < it.last_visible_y)
22028 {
22029 dvpos = (it.vpos
22030 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
22031 current_matrix));
22032 dy = it.current_y - first_unchanged_at_end_row->y;
22033 run.current_y = first_unchanged_at_end_row->y;
22034 run.desired_y = run.current_y + dy;
22035 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
22036 }
22037 else
22038 {
22039 delta = delta_bytes = dvpos = dy
22040 = run.current_y = run.desired_y = run.height = 0;
22041 first_unchanged_at_end_row = NULL;
22042 }
22043 IF_DEBUG ((debug_dvpos = dvpos, debug_dy = dy));
22044
22045
22046
22047
22048
22049
22050
22051
22052
22053
22054 if (w->cursor.vpos < 0)
22055 {
22056
22057 if (PT < CHARPOS (start_pos)
22058 && last_unchanged_at_beg_row)
22059 {
22060 row = row_containing_pos (w, PT,
22061 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
22062 last_unchanged_at_beg_row + 1, 0);
22063 if (row)
22064 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
22065 }
22066
22067
22068 else if (first_unchanged_at_end_row)
22069 {
22070 row = row_containing_pos (w, PT - delta,
22071 first_unchanged_at_end_row, NULL, 0);
22072 if (row)
22073 set_cursor_from_row (w, row, w->current_matrix, delta,
22074 delta_bytes, dy, dvpos);
22075 }
22076
22077
22078 if (w->cursor.vpos < 0)
22079 {
22080 clear_glyph_matrix (w->desired_matrix);
22081 return -1;
22082 }
22083 }
22084
22085
22086 {
22087 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
22088 int bot_scroll_margin = top_scroll_margin;
22089 int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
22090
22091 if (window_wants_header_line (w))
22092 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
22093 if (window_wants_tab_line (w))
22094 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
22095
22096 if ((w->cursor.y < top_scroll_margin
22097 && CHARPOS (start) > BEGV)
22098
22099
22100 || (w->cursor.y
22101 + (cursor_row_fully_visible_p (w, false, true, true)
22102 ? 1
22103 : cursor_height + bot_scroll_margin)) > it.last_visible_y)
22104 {
22105 w->cursor.vpos = -1;
22106 clear_glyph_matrix (w->desired_matrix);
22107 return -1;
22108 }
22109 }
22110
22111
22112
22113
22114 if (dy && run.height)
22115 {
22116 update_begin (f);
22117
22118 if (FRAME_WINDOW_P (f))
22119 {
22120 #ifdef HAVE_WINDOW_SYSTEM
22121 gui_update_window_begin (w);
22122 FRAME_RIF (f)->clear_window_mouse_face (w);
22123 FRAME_RIF (f)->scroll_run_hook (w, &run);
22124 gui_update_window_end (w, false, false);
22125 #endif
22126 }
22127 else
22128 {
22129
22130
22131 int from_vpos
22132 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
22133 int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos;
22134 int end = (WINDOW_TOP_EDGE_LINE (w)
22135 + window_wants_tab_line (w)
22136 + window_wants_header_line (w)
22137 + window_internal_height (w));
22138
22139 gui_clear_window_mouse_face (w);
22140
22141
22142 if (dvpos > 0)
22143 {
22144
22145
22146 set_terminal_window (f, end);
22147
22148
22149
22150 if (!FRAME_SCROLL_REGION_OK (f))
22151 ins_del_lines (f, end - dvpos, -dvpos);
22152
22153
22154
22155 ins_del_lines (f, from, dvpos);
22156 }
22157 else if (dvpos < 0)
22158 {
22159
22160
22161 set_terminal_window (f, end);
22162
22163
22164
22165
22166
22167 ins_del_lines (f, from + dvpos, dvpos);
22168
22169
22170
22171 if (!FRAME_SCROLL_REGION_OK (f))
22172 ins_del_lines (f, end + dvpos, -dvpos);
22173 }
22174
22175 set_terminal_window (f, 0);
22176 }
22177
22178 update_end (f);
22179 }
22180
22181
22182
22183
22184 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
22185 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
22186 if (dvpos < 0)
22187 {
22188 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
22189 bottom_vpos, dvpos);
22190 clear_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
22191 bottom_vpos);
22192 }
22193 else if (dvpos > 0)
22194 {
22195 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
22196 bottom_vpos, dvpos);
22197 clear_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
22198 first_unchanged_at_end_vpos + dvpos);
22199 }
22200
22201
22202
22203 if (!FRAME_WINDOW_P (f))
22204 sync_frame_with_window_matrix_rows (w);
22205
22206
22207 if (delta || delta_bytes)
22208 increment_matrix_positions (current_matrix,
22209 first_unchanged_at_end_vpos + dvpos,
22210 bottom_vpos, delta, delta_bytes);
22211
22212
22213 if (dy)
22214 shift_glyph_matrix (w, current_matrix,
22215 first_unchanged_at_end_vpos + dvpos,
22216 bottom_vpos, dy);
22217
22218 if (first_unchanged_at_end_row)
22219 {
22220 first_unchanged_at_end_row += dvpos;
22221 if (first_unchanged_at_end_row->y >= it.last_visible_y
22222 || !MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row))
22223 first_unchanged_at_end_row = NULL;
22224 }
22225
22226
22227
22228 last_text_row_at_end = NULL;
22229 if (dy < 0)
22230 {
22231
22232
22233
22234
22235
22236 int last_vpos = w->window_end_vpos + dvpos;
22237 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
22238
22239
22240 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_row));
22241
22242
22243
22244
22245 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
22246 {
22247 init_to_row_start (&it, w, last_row);
22248 it.vpos = last_vpos;
22249 it.current_y = last_row->y;
22250 }
22251 else
22252 {
22253 init_to_row_end (&it, w, last_row);
22254 it.vpos = 1 + last_vpos;
22255 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
22256 ++last_row;
22257 }
22258
22259
22260
22261 it.continuation_lines_width = last_row->continuation_lines_width;
22262 it.hpos = it.current_x = 0;
22263
22264
22265 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22266 while (it.current_y < it.last_visible_y && !f->fonts_changed)
22267 {
22268
22269
22270
22271
22272 SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false);
22273 if (display_line (&it, w->cursor.vpos))
22274 last_text_row_at_end = it.glyph_row - 1;
22275 }
22276 }
22277
22278
22279 if (first_unchanged_at_end_row && !last_text_row_at_end)
22280 {
22281
22282
22283
22284
22285 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22286 row = find_last_row_displaying_text (w->current_matrix, &it,
22287 first_unchanged_at_end_row);
22288 eassume (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
22289 adjust_window_ends (w, row, true);
22290 eassert (w->window_end_bytepos >= 0);
22291 IF_DEBUG (debug_method_add (w, "A"));
22292 }
22293 else if (last_text_row_at_end)
22294 {
22295 adjust_window_ends (w, last_text_row_at_end, false);
22296 eassert (w->window_end_bytepos >= 0);
22297 IF_DEBUG (debug_method_add (w, "B"));
22298 }
22299 else if (last_text_row)
22300 {
22301
22302
22303
22304 adjust_window_ends (w, last_text_row, false);
22305 eassert (w->window_end_bytepos >= 0);
22306 }
22307 else if (first_unchanged_at_end_row == NULL
22308 && last_text_row == NULL
22309 && last_text_row_at_end == NULL)
22310 {
22311
22312
22313 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
22314 int vpos = w->window_end_vpos;
22315 struct glyph_row *current_row = current_matrix->rows + vpos;
22316 struct glyph_row *desired_row = desired_matrix->rows + vpos;
22317
22318 for (row = NULL; !row; --vpos, --current_row, --desired_row)
22319 {
22320 eassert (first_vpos <= vpos);
22321 if (desired_row->enabled_p)
22322 {
22323 if (MATRIX_ROW_DISPLAYS_TEXT_P (desired_row))
22324 row = desired_row;
22325 }
22326 else if (MATRIX_ROW_DISPLAYS_TEXT_P (current_row))
22327 row = current_row;
22328 }
22329
22330 w->window_end_vpos = vpos + 1;
22331 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22332 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22333 eassert (w->window_end_bytepos >= 0);
22334 IF_DEBUG (debug_method_add (w, "C"));
22335 }
22336 else
22337 emacs_abort ();
22338
22339 IF_DEBUG ((debug_end_pos = w->window_end_pos,
22340 debug_end_vpos = w->window_end_vpos));
22341
22342
22343 w->window_end_valid = false;
22344 w->desired_matrix->no_scrolling_p = true;
22345 return 3;
22346
22347 #undef GIVE_UP
22348 }
22349
22350
22351
22352
22353
22354
22355
22356 #ifdef GLYPH_DEBUG
22357
22358 void dump_glyph_row (struct glyph_row *, int, int) EXTERNALLY_VISIBLE;
22359 void dump_glyph_matrix (struct glyph_matrix *, int) EXTERNALLY_VISIBLE;
22360 void dump_glyph (struct glyph_row *, struct glyph *, int) EXTERNALLY_VISIBLE;
22361
22362
22363
22364
22365
22366
22367
22368
22369 void
22370 dump_glyph_matrix (struct glyph_matrix *matrix, int glyphs)
22371 {
22372 int i;
22373 for (i = 0; i < matrix->nrows; ++i)
22374 dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
22375 }
22376
22377
22378
22379
22380
22381 void
22382 dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
22383 {
22384 if (glyph->type == CHAR_GLYPH
22385 || glyph->type == GLYPHLESS_GLYPH)
22386 {
22387 fprintf (stderr,
22388 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22389 glyph - row->glyphs[TEXT_AREA],
22390 (glyph->type == CHAR_GLYPH
22391 ? 'C'
22392 : 'G'),
22393 glyph->charpos,
22394 (BUFFERP (glyph->object)
22395 ? 'B'
22396 : (STRINGP (glyph->object)
22397 ? 'S'
22398 : (NILP (glyph->object)
22399 ? '0'
22400 : '-'))),
22401 glyph->pixel_width,
22402 glyph->u.ch,
22403 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
22404 ? (int) glyph->u.ch
22405 : '.'),
22406 glyph->face_id,
22407 glyph->left_box_line_p,
22408 glyph->right_box_line_p);
22409 }
22410 else if (glyph->type == STRETCH_GLYPH)
22411 {
22412 fprintf (stderr,
22413 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22414 glyph - row->glyphs[TEXT_AREA],
22415 'S',
22416 glyph->charpos,
22417 (BUFFERP (glyph->object)
22418 ? 'B'
22419 : (STRINGP (glyph->object)
22420 ? 'S'
22421 : (NILP (glyph->object)
22422 ? '0'
22423 : '-'))),
22424 glyph->pixel_width,
22425 0u,
22426 ' ',
22427 glyph->face_id,
22428 glyph->left_box_line_p,
22429 glyph->right_box_line_p);
22430 }
22431 else if (glyph->type == IMAGE_GLYPH)
22432 {
22433 fprintf (stderr,
22434 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22435 glyph - row->glyphs[TEXT_AREA],
22436 'I',
22437 glyph->charpos,
22438 (BUFFERP (glyph->object)
22439 ? 'B'
22440 : (STRINGP (glyph->object)
22441 ? 'S'
22442 : (NILP (glyph->object)
22443 ? '0'
22444 : '-'))),
22445 glyph->pixel_width,
22446 (unsigned int) glyph->u.img_id,
22447 '.',
22448 glyph->face_id,
22449 glyph->left_box_line_p,
22450 glyph->right_box_line_p);
22451 }
22452 else if (glyph->type == COMPOSITE_GLYPH)
22453 {
22454 fprintf (stderr,
22455 " %5"pD"d %c %9"pD"d %c %3d 0x%06x",
22456 glyph - row->glyphs[TEXT_AREA],
22457 '+',
22458 glyph->charpos,
22459 (BUFFERP (glyph->object)
22460 ? 'B'
22461 : (STRINGP (glyph->object)
22462 ? 'S'
22463 : (NILP (glyph->object)
22464 ? '0'
22465 : '-'))),
22466 glyph->pixel_width,
22467 (unsigned int) glyph->u.cmp.id);
22468 if (glyph->u.cmp.automatic)
22469 fprintf (stderr,
22470 "[%d-%d]",
22471 glyph->slice.cmp.from, glyph->slice.cmp.to);
22472 fprintf (stderr, " . %4d %1.1d%1.1d\n",
22473 glyph->face_id,
22474 glyph->left_box_line_p,
22475 glyph->right_box_line_p);
22476 }
22477 else if (glyph->type == XWIDGET_GLYPH)
22478 {
22479 #ifndef HAVE_XWIDGETS
22480 eassume (false);
22481 #else
22482 fprintf (stderr,
22483 " %5td %4c %6td %c %3d %7p %c %4d %1.1d%1.1d\n",
22484 glyph - row->glyphs[TEXT_AREA],
22485 'X',
22486 glyph->charpos,
22487 (BUFFERP (glyph->object)
22488 ? 'B'
22489 : (STRINGP (glyph->object)
22490 ? 'S'
22491 : '-')),
22492 glyph->pixel_width,
22493 glyph->u.xwidget,
22494 '.',
22495 glyph->face_id,
22496 glyph->left_box_line_p,
22497 glyph->right_box_line_p);
22498 #endif
22499 }
22500 }
22501
22502
22503
22504
22505
22506
22507
22508 void
22509 dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
22510 {
22511 if (glyphs != 1)
22512 {
22513 fputs (("Row Start End Used oE><\\CTZFesm X Y W H V A P\n"
22514 "==============================================================================\n"),
22515 stderr);
22516 fprintf (stderr, "%3d %9"pD"d %9"pD"d %4d %1.1d%1.1d%1.1d%1.1d\
22517 %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
22518 vpos,
22519 MATRIX_ROW_START_CHARPOS (row),
22520 MATRIX_ROW_END_CHARPOS (row),
22521 row->used[TEXT_AREA],
22522 row->contains_overlapping_glyphs_p,
22523 row->enabled_p,
22524 row->truncated_on_left_p,
22525 row->truncated_on_right_p,
22526 row->continued_p,
22527 MATRIX_ROW_CONTINUATION_LINE_P (row),
22528 MATRIX_ROW_DISPLAYS_TEXT_P (row),
22529 row->ends_at_zv_p,
22530 row->fill_line_p,
22531 row->ends_in_middle_of_char_p,
22532 row->starts_in_middle_of_char_p,
22533 row->mouse_face_p,
22534 row->x,
22535 row->y,
22536 row->pixel_width,
22537 row->height,
22538 row->visible_height,
22539 row->ascent,
22540 row->phys_ascent);
22541
22542 fprintf (stderr, " %9"pD"d %9"pD"d\t%5d\n", row->start.overlay_string_index,
22543 row->end.overlay_string_index,
22544 row->continuation_lines_width);
22545 fprintf (stderr, " %9"pD"d %9"pD"d\n",
22546 CHARPOS (row->start.string_pos),
22547 CHARPOS (row->end.string_pos));
22548 fprintf (stderr, " %9d %9d\n", row->start.dpvec_index,
22549 row->end.dpvec_index);
22550 }
22551
22552 if (glyphs > 1)
22553 {
22554 int area;
22555
22556 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22557 {
22558 struct glyph *glyph = row->glyphs[area];
22559 struct glyph *glyph_end = glyph + row->used[area];
22560
22561
22562 if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
22563 ++glyph_end;
22564
22565 if (glyph < glyph_end)
22566 fputs (" Glyph# Type Pos O W Code C Face LR\n",
22567 stderr);
22568
22569 for (; glyph < glyph_end; ++glyph)
22570 dump_glyph (row, glyph, area);
22571 }
22572 }
22573 else if (glyphs == 1)
22574 {
22575 int area;
22576 char s[SHRT_MAX + 4];
22577
22578 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22579 {
22580 int i;
22581
22582 for (i = 0; i < row->used[area]; ++i)
22583 {
22584 struct glyph *glyph = row->glyphs[area] + i;
22585 if (i == row->used[area] - 1
22586 && area == TEXT_AREA
22587 && NILP (glyph->object)
22588 && glyph->type == CHAR_GLYPH
22589 && glyph->u.ch == ' ')
22590 {
22591 strcpy (&s[i], "[\\n]");
22592 i += 4;
22593 }
22594 else if (glyph->type == CHAR_GLYPH
22595 && glyph->u.ch < 0x80
22596 && glyph->u.ch >= ' ')
22597 s[i] = glyph->u.ch;
22598 else
22599 s[i] = '.';
22600 }
22601
22602 s[i] = '\0';
22603 fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
22604 }
22605 }
22606 }
22607
22608
22609 DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
22610 Sdump_glyph_matrix, 0, 1, "p",
22611 doc:
22612
22613
22614
22615
22616
22617 )
22618 (Lisp_Object glyphs)
22619 {
22620 struct window *w = XWINDOW (selected_window);
22621 struct buffer *buffer = XBUFFER (w->contents);
22622
22623 fprintf (stderr, "PT = %"pD"d, BEGV = %"pD"d. ZV = %"pD"d\n",
22624 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
22625 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
22626 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
22627 fputs ("=============================================\n", stderr);
22628 dump_glyph_matrix (w->current_matrix,
22629 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 0);
22630 return Qnil;
22631 }
22632
22633
22634 DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
22635 Sdump_frame_glyph_matrix, 0, 0, "", doc:
22636 )
22637 (void)
22638 {
22639 struct frame *f = XFRAME (selected_frame);
22640
22641 if (f->current_matrix)
22642 dump_glyph_matrix (f->current_matrix, 1);
22643 else
22644 fputs ("*** This frame doesn't have a frame glyph matrix ***\n", stderr);
22645 return Qnil;
22646 }
22647
22648
22649 DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "P",
22650 doc:
22651
22652
22653
22654
22655 )
22656 (Lisp_Object row, Lisp_Object glyphs)
22657 {
22658 struct glyph_matrix *matrix;
22659 EMACS_INT vpos;
22660
22661 if (NILP (row))
22662 {
22663 int d1, d2, d3, d4, d5, ypos;
22664 bool visible_p = pos_visible_p (XWINDOW (selected_window), PT,
22665 &d1, &d2, &d3, &d4, &d5, &ypos);
22666 if (visible_p)
22667 vpos = ypos;
22668 else
22669 vpos = 0;
22670 }
22671 else
22672 {
22673 CHECK_FIXNUM (row);
22674 vpos = XFIXNUM (row);
22675 }
22676 matrix = XWINDOW (selected_window)->current_matrix;
22677 if (vpos >= 0 && vpos < matrix->nrows)
22678 dump_glyph_row (MATRIX_ROW (matrix, vpos),
22679 vpos,
22680 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22681 return Qnil;
22682 }
22683
22684
22685 DEFUN ("dump-tab-bar-row", Fdump_tab_bar_row, Sdump_tab_bar_row, 1, 2, "P",
22686 doc:
22687
22688
22689
22690
22691
22692
22693 )
22694 (Lisp_Object row, Lisp_Object glyphs)
22695 {
22696 #if defined (HAVE_WINDOW_SYSTEM)
22697 struct frame *sf = SELECTED_FRAME ();
22698 struct glyph_matrix *m = WINDOWP (sf->tab_bar_window)
22699 ? XWINDOW (sf->tab_bar_window)->current_matrix
22700 : sf->current_matrix;
22701 EMACS_INT vpos;
22702
22703 if (NILP (row))
22704 vpos = WINDOWP (sf->tab_bar_window) ? 0 :
22705 FRAME_MENU_BAR_LINES (sf) > 0 ? 1 : 0;
22706 else
22707 {
22708 CHECK_FIXNUM (row);
22709 vpos = XFIXNUM (row);
22710 }
22711 if (vpos >= 0 && vpos < m->nrows)
22712 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22713 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22714 #endif
22715 return Qnil;
22716 }
22717
22718 DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "P",
22719 doc:
22720
22721
22722
22723
22724
22725
22726 )
22727 (Lisp_Object row, Lisp_Object glyphs)
22728 {
22729 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
22730 struct frame *sf = SELECTED_FRAME ();
22731 struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
22732 EMACS_INT vpos;
22733
22734 if (NILP (row))
22735 vpos = 0;
22736 else
22737 {
22738 CHECK_FIXNUM (row);
22739 vpos = XFIXNUM (row);
22740 }
22741 if (vpos >= 0 && vpos < m->nrows)
22742 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22743 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22744 #endif
22745 return Qnil;
22746 }
22747
22748
22749 DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
22750 doc:
22751 )
22752 (Lisp_Object arg)
22753 {
22754 if (NILP (arg))
22755 trace_redisplay_p = !trace_redisplay_p;
22756 else
22757 {
22758 arg = Fprefix_numeric_value (arg);
22759 trace_redisplay_p = XFIXNUM (arg) > 0;
22760 }
22761
22762 return Qnil;
22763 }
22764
22765
22766 DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
22767 doc:
22768 )
22769 (ptrdiff_t nargs, Lisp_Object *args)
22770 {
22771 Lisp_Object s = Fformat (nargs, args);
22772 fwrite (SDATA (s), 1, SBYTES (s), stderr);
22773 return Qnil;
22774 }
22775
22776 #endif
22777
22778
22779
22780
22781
22782
22783
22784
22785
22786
22787
22788 static struct glyph_row *
22789 get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
22790 {
22791 struct frame *f = XFRAME (WINDOW_FRAME (w));
22792 struct buffer *buffer = XBUFFER (w->contents);
22793 struct buffer *old = current_buffer;
22794 const unsigned char *arrow_string = SDATA (overlay_arrow_string);
22795 ptrdiff_t arrow_len = SBYTES (overlay_arrow_string), char_num = 0;
22796 const unsigned char *arrow_end = arrow_string + arrow_len;
22797 const unsigned char *p;
22798 struct it it;
22799 bool multibyte_p;
22800 int n_glyphs_before;
22801
22802 set_buffer_temp (buffer);
22803 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
22804 scratch_glyph_row.reversed_p = false;
22805 it.glyph_row->used[TEXT_AREA] = 0;
22806 SET_TEXT_POS (it.position, 0, 0);
22807
22808 multibyte_p = !NILP (BVAR (buffer, enable_multibyte_characters));
22809 p = arrow_string;
22810 while (p < arrow_end)
22811 {
22812 Lisp_Object face, ilisp;
22813
22814
22815 if (multibyte_p)
22816 it.c = it.char_to_display = check_char_and_length (p, &it.len);
22817 else
22818 {
22819 it.c = it.char_to_display = *p, it.len = 1;
22820 if (! ASCII_CHAR_P (it.c))
22821 it.char_to_display = BYTE8_TO_CHAR (it.c);
22822 }
22823 p += it.len;
22824
22825
22826 ilisp = make_fixnum (char_num++);
22827 face = Fget_text_property (ilisp, Qface, overlay_arrow_string);
22828 it.face_id = compute_char_face (f, it.char_to_display, face);
22829
22830
22831 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
22832 SET_TEXT_POS (it.position, -1, -1);
22833 PRODUCE_GLYPHS (&it);
22834
22835
22836
22837 if (it.current_x > it.last_visible_x)
22838 {
22839 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
22840 break;
22841 }
22842 }
22843
22844 set_buffer_temp (old);
22845 return it.glyph_row;
22846 }
22847
22848
22849
22850
22851
22852 static void
22853 insert_left_trunc_glyphs (struct it *it)
22854 {
22855 struct it truncate_it;
22856 struct glyph *from, *end, *to, *toend;
22857
22858 eassert (!FRAME_WINDOW_P (it->f)
22859 || (!it->glyph_row->reversed_p
22860 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
22861 || (it->glyph_row->reversed_p
22862 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0));
22863
22864
22865 truncate_it = *it;
22866 truncate_it.current_x = 0;
22867 truncate_it.face_id = DEFAULT_FACE_ID;
22868 truncate_it.glyph_row = &scratch_glyph_row;
22869 truncate_it.area = TEXT_AREA;
22870 truncate_it.glyph_row->used[TEXT_AREA] = 0;
22871 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
22872 truncate_it.object = Qnil;
22873 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
22874
22875
22876 if (!it->glyph_row->reversed_p)
22877 {
22878 short tused = truncate_it.glyph_row->used[TEXT_AREA];
22879
22880 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
22881 end = from + tused;
22882 to = it->glyph_row->glyphs[TEXT_AREA];
22883 toend = to + it->glyph_row->used[TEXT_AREA];
22884 if (FRAME_WINDOW_P (it->f))
22885 {
22886
22887
22888
22889
22890
22891
22892
22893 int w = 0;
22894 struct glyph *g = to;
22895 short used;
22896
22897
22898
22899
22900
22901
22902 it->glyph_row->x = 0;
22903 while (g < toend && w < it->truncation_pixel_width)
22904 {
22905 w += g->pixel_width;
22906 ++g;
22907 }
22908 if (g - to - tused > 0)
22909 {
22910 memmove (to + tused, g, (toend - g) * sizeof(*g));
22911 it->glyph_row->used[TEXT_AREA] -= g - to - tused;
22912 }
22913 used = it->glyph_row->used[TEXT_AREA];
22914 if (it->glyph_row->truncated_on_right_p
22915 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
22916 && it->glyph_row->glyphs[TEXT_AREA][used - 2].type
22917 == STRETCH_GLYPH)
22918 {
22919 int extra = w - it->truncation_pixel_width;
22920
22921 it->glyph_row->glyphs[TEXT_AREA][used - 2].pixel_width += extra;
22922 }
22923 }
22924
22925 while (from < end)
22926 *to++ = *from++;
22927
22928
22929 if (!FRAME_WINDOW_P (it->f))
22930 {
22931 while (to < toend && CHAR_GLYPH_PADDING_P (*to))
22932 {
22933 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
22934 while (from < end)
22935 *to++ = *from++;
22936 }
22937 }
22938
22939 if (to > toend)
22940 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
22941 }
22942 else
22943 {
22944 short tused = truncate_it.glyph_row->used[TEXT_AREA];
22945
22946
22947
22948 end = truncate_it.glyph_row->glyphs[TEXT_AREA];
22949 from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1;
22950 toend = it->glyph_row->glyphs[TEXT_AREA];
22951 to = toend + it->glyph_row->used[TEXT_AREA] - 1;
22952 if (FRAME_WINDOW_P (it->f))
22953 {
22954 int w = 0;
22955 struct glyph *g = to;
22956
22957 while (g >= toend && w < it->truncation_pixel_width)
22958 {
22959 w += g->pixel_width;
22960 --g;
22961 }
22962 if (to - g - tused > 0)
22963 to = g + tused;
22964 if (it->glyph_row->truncated_on_right_p
22965 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
22966 && it->glyph_row->glyphs[TEXT_AREA][1].type == STRETCH_GLYPH)
22967 {
22968 int extra = w - it->truncation_pixel_width;
22969
22970 it->glyph_row->glyphs[TEXT_AREA][1].pixel_width += extra;
22971 }
22972 }
22973
22974 while (from >= end && to >= toend)
22975 *to-- = *from--;
22976 if (!FRAME_WINDOW_P (it->f))
22977 {
22978 while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
22979 {
22980 from =
22981 truncate_it.glyph_row->glyphs[TEXT_AREA]
22982 + truncate_it.glyph_row->used[TEXT_AREA] - 1;
22983 while (from >= end && to >= toend)
22984 *to-- = *from--;
22985 }
22986 }
22987 if (from >= end)
22988 {
22989
22990
22991 int move_by = from - end + 1;
22992 struct glyph *g0 = it->glyph_row->glyphs[TEXT_AREA];
22993 struct glyph *g = g0 + it->glyph_row->used[TEXT_AREA] - 1;
22994
22995 for ( ; g >= g0; g--)
22996 g[move_by] = *g;
22997 while (from >= end)
22998 *to-- = *from--;
22999 it->glyph_row->used[TEXT_AREA] += move_by;
23000 }
23001 }
23002 }
23003
23004
23005 unsigned
23006 row_hash (struct glyph_row *row)
23007 {
23008 int area, k;
23009 unsigned hashval = 0;
23010
23011 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
23012 for (k = 0; k < row->used[area]; ++k)
23013 hashval = ((((hashval << 4) + (hashval >> 24)) & 0x0fffffff)
23014 + row->glyphs[area][k].u.val
23015 + row->glyphs[area][k].face_id
23016 + row->glyphs[area][k].padding_p
23017 + (row->glyphs[area][k].type << 2));
23018
23019 return hashval;
23020 }
23021
23022
23023
23024
23025
23026
23027
23028
23029
23030
23031
23032
23033
23034
23035
23036
23037
23038
23039 static void
23040 compute_line_metrics (struct it *it)
23041 {
23042 struct glyph_row *row = it->glyph_row;
23043
23044 if (FRAME_WINDOW_P (it->f))
23045 {
23046 int i, min_y, max_y;
23047
23048
23049
23050
23051 if (row->height == 0)
23052 {
23053 if (it->max_ascent + it->max_descent == 0)
23054 it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
23055 row->ascent = it->max_ascent;
23056 row->height = it->max_ascent + it->max_descent;
23057 row->phys_ascent = it->max_phys_ascent;
23058 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
23059 row->extra_line_spacing = it->max_extra_line_spacing;
23060 }
23061
23062
23063 row->pixel_width = row->x;
23064 for (i = 0; i < row->used[TEXT_AREA]; ++i)
23065 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
23066
23067 eassert (row->pixel_width >= 0);
23068 eassert (row->ascent >= 0 && row->height > 0);
23069
23070 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
23071 || MATRIX_ROW_OVERLAPS_PRED_P (row));
23072
23073
23074
23075
23076 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
23077 && row->phys_ascent > row->ascent)
23078 {
23079 row->height += row->phys_ascent - row->ascent;
23080 row->ascent = row->phys_ascent;
23081 }
23082
23083
23084 row->visible_height = row->height;
23085
23086 min_y = WINDOW_TAB_LINE_HEIGHT (it->w) + WINDOW_HEADER_LINE_HEIGHT (it->w);
23087 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
23088
23089 if (row->y < min_y)
23090 row->visible_height -= min_y - row->y;
23091 if (row->y + row->height > max_y)
23092 row->visible_height -= row->y + row->height - max_y;
23093 }
23094 else
23095 {
23096 row->pixel_width = row->used[TEXT_AREA];
23097 if (row->continued_p)
23098 row->pixel_width -= it->continuation_pixel_width;
23099 else if (row->truncated_on_right_p)
23100 row->pixel_width -= it->truncation_pixel_width;
23101 row->ascent = row->phys_ascent = 0;
23102 row->height = row->phys_height = row->visible_height = 1;
23103 row->extra_line_spacing = 0;
23104 }
23105
23106
23107 row->hash = row_hash (row);
23108
23109 it->max_ascent = it->max_descent = 0;
23110 it->max_phys_ascent = it->max_phys_descent = 0;
23111 }
23112
23113
23114 static void
23115 clear_position (struct it *it)
23116 {
23117 it->position.charpos = 0;
23118 it->position.bytepos = 0;
23119 }
23120
23121
23122
23123
23124
23125
23126
23127
23128
23129
23130
23131
23132
23133 static bool
23134 append_space_for_newline (struct it *it, bool default_face_p)
23135 {
23136 int n = it->glyph_row->used[TEXT_AREA];
23137
23138 if (it->glyph_row->glyphs[TEXT_AREA] + n
23139 < it->glyph_row->glyphs[1 + TEXT_AREA])
23140 {
23141
23142
23143
23144
23145 enum display_element_type saved_what = it->what;
23146 int saved_c = it->c, saved_len = it->len;
23147 int saved_char_to_display = it->char_to_display;
23148 int saved_x = it->current_x;
23149 const int saved_face_id = it->face_id;
23150 bool saved_box_end = it->end_of_box_run_p;
23151 struct text_pos saved_pos = it->position;
23152 Lisp_Object saved_object = it->object;
23153 struct face *face;
23154
23155 it->what = IT_CHARACTER;
23156 clear_position (it);
23157 it->object = Qnil;
23158 it->len = 1;
23159
23160 int char_width = 1;
23161
23162 if (default_face_p
23163 #ifdef HAVE_WINDOW_SYSTEM
23164 || FRAME_WINDOW_P (it->f)
23165 #endif
23166 )
23167 {
23168 const int local_default_face_id =
23169 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
23170
23171 #ifdef HAVE_WINDOW_SYSTEM
23172 if (FRAME_WINDOW_P (it->f))
23173 {
23174 struct face *default_face
23175 = FACE_FROM_ID (it->f, local_default_face_id);
23176 struct font *font = (default_face->font
23177 ? default_face->font
23178 : FRAME_FONT (it->f));
23179 char_width = (font->average_width
23180 ? font->average_width
23181 : font->space_width);
23182 }
23183 #endif
23184 if (default_face_p)
23185 it->face_id = local_default_face_id;
23186 }
23187
23188
23189
23190
23191 const int indicator_column =
23192 fill_column_indicator_column (it, char_width);
23193 int saved_end_of_box_run = it->end_of_box_run_p;
23194 bool should_keep_end_of_box_run = false;
23195
23196 if (it->current_x == indicator_column)
23197 {
23198 it->c = it->char_to_display
23199 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23200 it->face_id
23201 = merge_faces (it->w, Qfill_column_indicator,
23202 0, saved_face_id);
23203 face = FACE_FROM_ID (it->f, it->face_id);
23204 }
23205 else
23206 {
23207 it->c = it->char_to_display = ' ';
23208
23209
23210
23211 face = FACE_FROM_ID (it->f, it->face_id);
23212 it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
23213
23214
23215
23216
23217 if (!(it->glyph_row->reversed_p
23218
23219
23220
23221 && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x))
23222 should_keep_end_of_box_run = true;
23223 }
23224 PRODUCE_GLYPHS (it);
23225
23226
23227 if (should_keep_end_of_box_run)
23228 it->end_of_box_run_p = saved_end_of_box_run;
23229 #ifdef HAVE_WINDOW_SYSTEM
23230 if (FRAME_WINDOW_P (it->f))
23231 {
23232
23233
23234
23235 struct glyph *g = it->glyph_row->glyphs[TEXT_AREA] + n;
23236 struct font *font = face->font ? face->font : FRAME_FONT (it->f);
23237 if (n == 0)
23238 {
23239 Lisp_Object height, total_height;
23240 int extra_line_spacing = it->extra_line_spacing;
23241 int boff = font->baseline_offset;
23242
23243 if (font->vertical_centering)
23244 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
23245
23246 it->object = saved_object;
23247 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
23248
23249
23250 height = get_it_property (it, Qline_height);
23251 if (CONSP (height)
23252 && CONSP (XCDR (height))
23253 && NILP (XCDR (XCDR (height))))
23254 {
23255 total_height = XCAR (XCDR (height));
23256 height = XCAR (height);
23257 }
23258 else
23259 total_height = Qnil;
23260 height = calc_line_height_property (it, height, font, boff, true);
23261
23262 if (it->override_ascent >= 0)
23263 {
23264 it->ascent = it->override_ascent;
23265 it->descent = it->override_descent;
23266 boff = it->override_boff;
23267 }
23268 if (EQ (height, Qt))
23269 extra_line_spacing = 0;
23270 else
23271 {
23272 Lisp_Object spacing;
23273
23274 it->phys_ascent = it->ascent;
23275 it->phys_descent = it->descent;
23276 if (!NILP (height)
23277 && XFIXNUM (height) > it->ascent + it->descent)
23278 it->ascent = XFIXNUM (height) - it->descent;
23279
23280 if (!NILP (total_height))
23281 spacing = calc_line_height_property (it, total_height, font,
23282 boff, false);
23283 else
23284 {
23285 spacing = get_it_property (it, Qline_spacing);
23286 spacing = calc_line_height_property (it, spacing, font,
23287 boff, false);
23288 }
23289 if (FIXNUMP (spacing))
23290 {
23291 extra_line_spacing = XFIXNUM (spacing);
23292 if (!NILP (total_height))
23293 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
23294 }
23295 }
23296 if (extra_line_spacing > 0)
23297 {
23298 it->descent += extra_line_spacing;
23299 if (extra_line_spacing > it->max_extra_line_spacing)
23300 it->max_extra_line_spacing = extra_line_spacing;
23301 }
23302 it->max_ascent = it->ascent;
23303 it->max_descent = it->descent;
23304
23305 it->glyph_row->height = 0;
23306 }
23307
23308 g->ascent = it->max_ascent;
23309 g->descent = it->max_descent;
23310 }
23311 #endif
23312 it->override_ascent = -1;
23313 it->constrain_row_ascent_descent_p = false;
23314 it->current_x = saved_x;
23315 it->object = saved_object;
23316 it->position = saved_pos;
23317 it->what = saved_what;
23318 it->face_id = saved_face_id;
23319 it->len = saved_len;
23320 it->c = saved_c;
23321 it->char_to_display = saved_char_to_display;
23322 it->end_of_box_run_p = saved_box_end;
23323 return true;
23324 }
23325
23326 return false;
23327 }
23328
23329
23330
23331
23332
23333
23334
23335
23336
23337 static void
23338 extend_face_to_end_of_line (struct it *it)
23339 {
23340 struct frame *f = it->f;
23341
23342
23343
23344
23345
23346
23347 if ((it->current_x >= it->last_visible_x
23348 + (!FRAME_WINDOW_P (f)
23349 && it->glyph_row->reversed_p
23350 && !it->glyph_row->continued_p))
23351
23352
23353 && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23354 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
23355 return;
23356
23357 specpdl_ref count = SPECPDL_INDEX ();
23358
23359
23360
23361
23362 specbind (Qinhibit_quit, Qt);
23363
23364 struct face *default_face =
23365 FACE_FROM_ID_OR_NULL (f, lookup_basic_face (it->w, f, DEFAULT_FACE_ID));
23366 if (!default_face)
23367 return;
23368
23369 const int extend_face_id =
23370 (it->face_id == default_face->id || it->s != NULL)
23371 ? it->face_id
23372 : (it->glyph_row->ends_at_zv_p
23373 ? default_face->id
23374 : face_at_pos (it, LFACE_EXTEND_INDEX));
23375 unbind_to (count, Qnil);
23376
23377
23378
23379
23380 struct face *face = FACE_FROM_ID (f, (it->face_before_selective_p
23381 ? it->saved_face_id
23382 : extend_face_id));
23383
23384 if (FRAME_WINDOW_P (f)
23385 && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
23386 && face->box == FACE_NO_BOX
23387 && face->underline == FACE_NO_UNDERLINE
23388 && !face->overline_p
23389 && !face->strike_through_p
23390 && face->background == FRAME_BACKGROUND_PIXEL (f)
23391 #ifdef HAVE_WINDOW_SYSTEM
23392 && !face->stipple
23393 #endif
23394 && !it->glyph_row->reversed_p
23395 && !display_fill_column_indicator)
23396 return;
23397
23398
23399
23400 it->glyph_row->fill_line_p = true;
23401
23402 const int orig_face_id = it->face_id;
23403
23404
23405
23406
23407
23408 if (!ASCII_CHAR_P (it->c))
23409 it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
23410
23411
23412 #ifdef HAVE_WINDOW_SYSTEM
23413 if (FRAME_WINDOW_P (f))
23414 {
23415
23416
23417 if (it->glyph_row->used[TEXT_AREA] == 0)
23418 {
23419 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
23420 it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
23421 it->glyph_row->used[TEXT_AREA] = 1;
23422 }
23423
23424
23425 if (!(it->glyph_row->mode_line_p
23426 || (WINDOWP (f->tab_bar_window)
23427 && it->w == XWINDOW (f->tab_bar_window))
23428 #ifndef HAVE_EXT_TOOL_BAR
23429 || (WINDOWP (f->tool_bar_window)
23430 && it->w == XWINDOW (f->tool_bar_window))
23431 #endif
23432 ))
23433 {
23434 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23435 && it->glyph_row->used[LEFT_MARGIN_AREA] == 0)
23436 {
23437 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
23438 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
23439 default_face->id;
23440 it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
23441 }
23442 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23443 && it->glyph_row->used[RIGHT_MARGIN_AREA] == 0)
23444 {
23445 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
23446 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
23447 default_face->id;
23448 it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
23449 }
23450
23451 struct font *font = (default_face->font
23452 ? default_face->font
23453 : FRAME_FONT (f));
23454
23455 const int char_width = (font->average_width
23456 ? font->average_width
23457 : font->space_width);
23458
23459 const int indicator_column =
23460 fill_column_indicator_column (it, char_width);
23461
23462 const char saved_char = it->char_to_display;
23463 const struct text_pos saved_pos = it->position;
23464 const bool saved_avoid_cursor = it->avoid_cursor_p;
23465 const bool saved_box_start = it->start_of_box_run_p;
23466 Lisp_Object save_object = it->object;
23467 const int saved_face_id = it->face_id;
23468
23469 it->face_id = extend_face_id;
23470 it->avoid_cursor_p = true;
23471 it->object = Qnil;
23472
23473 const int stretch_height = it->ascent + it->descent;
23474 const int stretch_ascent =
23475 (stretch_height * FONT_BASE (font)) / FONT_HEIGHT (font);
23476
23477 if (indicator_column >= 0
23478 && indicator_column > it->current_x
23479 && indicator_column < it->last_visible_x)
23480 {
23481
23482
23483
23484
23485 const int stretch_width =
23486 indicator_column - it->current_x - char_width;
23487
23488 clear_position (it);
23489
23490
23491
23492 if (stretch_width > 0)
23493 {
23494 append_stretch_glyph (it, Qnil, stretch_width,
23495 stretch_height, stretch_ascent);
23496 }
23497
23498
23499
23500 if (it->current_x < indicator_column)
23501 {
23502 const int save_face_id = it->face_id;
23503 const int save_ascent = it->ascent;
23504 const int save_descent = it->descent;
23505 it->char_to_display
23506 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23507 it->face_id
23508 = merge_faces (it->w, Qfill_column_indicator,
23509 0, extend_face_id);
23510 PRODUCE_GLYPHS (it);
23511 it->face_id = save_face_id;
23512 it->ascent = save_ascent;
23513 it->descent = save_descent;
23514 }
23515 }
23516
23517
23518
23519 if (!it->glyph_row->reversed_p)
23520 {
23521 const int stretch_width = it->last_visible_x - it->current_x;
23522
23523 if (stretch_width > 0)
23524 {
23525 clear_position (it);
23526 append_stretch_glyph (it, Qnil, stretch_width,
23527 stretch_height, stretch_ascent);
23528 }
23529 }
23530
23531 it->char_to_display = saved_char;
23532 it->position = saved_pos;
23533 it->avoid_cursor_p = saved_avoid_cursor;
23534 it->start_of_box_run_p = saved_box_start;
23535 it->object = save_object;
23536 it->face_id = saved_face_id;
23537 }
23538 if (it->glyph_row->reversed_p)
23539 {
23540
23541
23542
23543
23544
23545 struct font *font = face->font ? face->font : FRAME_FONT (f);
23546 struct glyph *row_start = it->glyph_row->glyphs[TEXT_AREA];
23547 struct glyph *row_end = row_start + it->glyph_row->used[TEXT_AREA];
23548 struct glyph *g;
23549 int row_width, stretch_ascent, stretch_width;
23550 struct text_pos saved_pos;
23551 int saved_face_id;
23552 bool saved_avoid_cursor, saved_box_start;
23553
23554 for (row_width = 0, g = row_start; g < row_end; g++)
23555 row_width += g->pixel_width;
23556
23557
23558
23559
23560 if ((WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23561 == (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
23562 || WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
23563 stretch_width = window_box_width (it->w, TEXT_AREA);
23564 else
23565 stretch_width = it->last_visible_x - it->first_visible_x;
23566 stretch_width -= row_width;
23567
23568 if (stretch_width > 0)
23569 {
23570 stretch_ascent =
23571 (((it->ascent + it->descent)
23572 * FONT_BASE (font)) / FONT_HEIGHT (font));
23573 saved_pos = it->position;
23574 clear_position (it);
23575 saved_avoid_cursor = it->avoid_cursor_p;
23576 it->avoid_cursor_p = true;
23577 saved_face_id = it->face_id;
23578 saved_box_start = it->start_of_box_run_p;
23579
23580
23581
23582 it->face_id = (it->glyph_row->ends_at_zv_p ?
23583 default_face->id : face->id);
23584
23585 it->start_of_box_run_p = false;
23586 append_stretch_glyph (it, Qnil, stretch_width,
23587 it->ascent + it->descent, stretch_ascent);
23588 it->position = saved_pos;
23589 it->avoid_cursor_p = saved_avoid_cursor;
23590 it->face_id = saved_face_id;
23591 it->start_of_box_run_p = saved_box_start;
23592 }
23593
23594
23595
23596
23597 if (stretch_width < 0)
23598 it->glyph_row->x = stretch_width;
23599 }
23600 it->face_id = orig_face_id;
23601 }
23602 else
23603 #endif
23604 {
23605
23606 int saved_x = it->current_x;
23607 struct text_pos saved_pos = it->position;
23608 Lisp_Object saved_object = it->object;;
23609 enum display_element_type saved_what = it->what;
23610
23611 it->what = IT_CHARACTER;
23612 clear_position (it);
23613 it->object = Qnil;
23614 it->c = it->char_to_display = ' ';
23615 it->len = 1;
23616
23617 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23618 && (it->glyph_row->used[LEFT_MARGIN_AREA]
23619 < WINDOW_LEFT_MARGIN_WIDTH (it->w))
23620 && !it->glyph_row->mode_line_p
23621 && face->background != FRAME_BACKGROUND_PIXEL (f))
23622 {
23623 struct glyph *g = it->glyph_row->glyphs[LEFT_MARGIN_AREA];
23624 struct glyph *e = g + it->glyph_row->used[LEFT_MARGIN_AREA];
23625
23626 for (it->current_x = 0; g < e; g++)
23627 it->current_x += g->pixel_width;
23628
23629 it->area = LEFT_MARGIN_AREA;
23630 it->face_id = default_face->id;
23631 while (it->glyph_row->used[LEFT_MARGIN_AREA]
23632 < WINDOW_LEFT_MARGIN_WIDTH (it->w)
23633 && g < it->glyph_row->glyphs[TEXT_AREA])
23634 {
23635 PRODUCE_GLYPHS (it);
23636
23637
23638 it->current_x += it->pixel_width;
23639 g++;
23640 }
23641
23642 it->current_x = saved_x;
23643 it->area = TEXT_AREA;
23644 }
23645
23646
23647
23648
23649 it->face_id = (it->glyph_row->ends_at_zv_p ?
23650 default_face->id : face->id);
23651
23652
23653
23654
23655
23656 it->current_x = it->glyph_row->used[TEXT_AREA];
23657
23658
23659
23660
23661
23662
23663
23664
23665 const int indicator_column =
23666 fill_column_indicator_column (it, 1) - it->first_visible_x;
23667
23668
23669 while (it->current_x <= it->last_visible_x)
23670 {
23671 if (it->current_x != indicator_column)
23672 PRODUCE_GLYPHS (it);
23673 else
23674 {
23675 int saved_face_id = it->face_id;
23676 it->face_id
23677 = merge_faces (it->w, Qfill_column_indicator, 0, extend_face_id);
23678 it->c = it->char_to_display
23679 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23680
23681 PRODUCE_GLYPHS (it);
23682
23683 it->face_id = saved_face_id;
23684 it->c = it->char_to_display = ' ';
23685 }
23686 }
23687
23688 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23689 && (it->glyph_row->used[RIGHT_MARGIN_AREA]
23690 < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
23691 && !it->glyph_row->mode_line_p
23692 && face->background != FRAME_BACKGROUND_PIXEL (f))
23693 {
23694 struct glyph *g = it->glyph_row->glyphs[RIGHT_MARGIN_AREA];
23695 struct glyph *e = g + it->glyph_row->used[RIGHT_MARGIN_AREA];
23696
23697 for ( ; g < e; g++)
23698 it->current_x += g->pixel_width;
23699
23700 it->area = RIGHT_MARGIN_AREA;
23701 it->face_id = default_face->id;
23702 while (it->glyph_row->used[RIGHT_MARGIN_AREA]
23703 < WINDOW_RIGHT_MARGIN_WIDTH (it->w)
23704 && g < it->glyph_row->glyphs[LAST_AREA])
23705 {
23706 PRODUCE_GLYPHS (it);
23707 it->current_x += it->pixel_width;
23708 g++;
23709 }
23710
23711 it->area = TEXT_AREA;
23712 }
23713
23714
23715
23716 it->current_x = saved_x;
23717 it->object = saved_object;
23718 it->position = saved_pos;
23719 it->what = saved_what;
23720 it->face_id = orig_face_id;
23721 }
23722 }
23723
23724
23725
23726
23727
23728 static bool
23729 trailing_whitespace_p (ptrdiff_t charpos)
23730 {
23731 ptrdiff_t bytepos = CHAR_TO_BYTE (charpos);
23732 int c = 0;
23733
23734 while (bytepos < ZV_BYTE
23735 && (c = FETCH_BYTE (bytepos),
23736 c == ' ' || c == '\t'))
23737 ++bytepos;
23738
23739 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
23740 {
23741 if (bytepos != PT_BYTE)
23742 return true;
23743 }
23744 return false;
23745 }
23746
23747
23748
23749
23750 static void
23751 highlight_trailing_whitespace (struct it *it)
23752 {
23753 struct glyph_row *row = it->glyph_row;
23754 int used = row->used[TEXT_AREA];
23755
23756 if (used)
23757 {
23758 struct glyph *start = row->glyphs[TEXT_AREA];
23759 struct glyph *glyph = start + used - 1;
23760
23761 if (row->reversed_p)
23762 {
23763
23764
23765 glyph = start;
23766 start = row->glyphs[TEXT_AREA] + used - 1;
23767 }
23768
23769
23770
23771
23772
23773 if (!row->reversed_p)
23774 {
23775 while (glyph >= start
23776 && (glyph->type == CHAR_GLYPH
23777 || glyph->type == STRETCH_GLYPH)
23778 && NILP (glyph->object))
23779 --glyph;
23780 }
23781 else
23782 {
23783 while (glyph <= start
23784 && (glyph->type == CHAR_GLYPH || glyph->type == STRETCH_GLYPH)
23785 && NILP (glyph->object))
23786 ++glyph;
23787 }
23788
23789
23790
23791
23792 if ((row->reversed_p ? glyph <= start : glyph >= start)
23793 && BUFFERP (glyph->object)
23794 && (glyph->type == STRETCH_GLYPH
23795 || (glyph->type == CHAR_GLYPH
23796 && glyph->u.ch == ' '))
23797 && trailing_whitespace_p (glyph->charpos))
23798 {
23799 int face_id = lookup_named_face (it->w, it->f, Qtrailing_whitespace, false);
23800 if (face_id < 0)
23801 return;
23802
23803 if (!row->reversed_p)
23804 {
23805 while (glyph >= start
23806 && BUFFERP (glyph->object)
23807 && (glyph->type == STRETCH_GLYPH
23808 || (glyph->type == CHAR_GLYPH
23809 && glyph->u.ch == ' ')))
23810 (glyph--)->face_id = face_id;
23811 }
23812 else
23813 {
23814 while (glyph <= start
23815 && BUFFERP (glyph->object)
23816 && (glyph->type == STRETCH_GLYPH
23817 || (glyph->type == CHAR_GLYPH
23818 && glyph->u.ch == ' ')))
23819 (glyph++)->face_id = face_id;
23820 }
23821 }
23822 }
23823 }
23824
23825
23826
23827
23828
23829 static bool
23830 row_for_charpos_p (struct glyph_row *row, ptrdiff_t charpos)
23831 {
23832 bool result = true;
23833
23834 if (charpos == CHARPOS (row->end.pos)
23835 || charpos == MATRIX_ROW_END_CHARPOS (row))
23836 {
23837
23838
23839
23840
23841
23842
23843
23844
23845 if (CHARPOS (row->end.string_pos) >= 0)
23846 {
23847 if (row->continued_p)
23848 result = true;
23849 else
23850 {
23851
23852 struct glyph *beg = row->glyphs[TEXT_AREA];
23853 struct glyph *end = beg + row->used[TEXT_AREA] - 1;
23854 struct glyph *glyph;
23855
23856 result = false;
23857 for (glyph = end; glyph >= beg; --glyph)
23858 if (STRINGP (glyph->object))
23859 {
23860 Lisp_Object prop
23861 = Fget_char_property (make_fixnum (charpos),
23862 Qdisplay, Qnil);
23863 result =
23864 (!NILP (prop)
23865 && display_prop_string_p (prop, glyph->object));
23866
23867
23868
23869 if (!result)
23870 {
23871 Lisp_Object s = glyph->object;
23872
23873 for ( ; glyph >= beg && EQ (glyph->object, s); --glyph)
23874 {
23875 ptrdiff_t gpos = glyph->charpos;
23876
23877 if (!NILP (Fget_char_property (make_fixnum (gpos),
23878 Qcursor, s)))
23879 {
23880 result = true;
23881 break;
23882 }
23883 }
23884 }
23885 break;
23886 }
23887 }
23888 }
23889 else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
23890 {
23891
23892
23893
23894
23895 if (!row->ends_in_ellipsis_p)
23896 result = row->continued_p;
23897 else
23898
23899
23900
23901
23902 result = false;
23903 }
23904
23905
23906 else
23907 result = row->ends_at_zv_p;
23908 }
23909
23910 return result;
23911 }
23912
23913
23914
23915
23916 static bool
23917 cursor_row_p (struct glyph_row *row)
23918 {
23919 return row_for_charpos_p (row, PT);
23920 }
23921
23922
23923
23924
23925
23926
23927
23928
23929 static bool
23930 push_prefix_prop (struct it *it, Lisp_Object prop)
23931 {
23932 struct text_pos pos =
23933 STRINGP (it->string) ? it->current.string_pos : it->current.pos;
23934
23935 eassert (it->method == GET_FROM_BUFFER
23936 || it->method == GET_FROM_DISPLAY_VECTOR
23937 || it->method == GET_FROM_STRING
23938 || it->method == GET_FROM_IMAGE);
23939
23940
23941
23942
23943
23944 push_it (it, &pos);
23945
23946 if (STRINGP (prop))
23947 {
23948 if (SCHARS (prop) == 0)
23949 {
23950 pop_it (it);
23951 return false;
23952 }
23953
23954 it->string = prop;
23955 it->string_from_prefix_prop_p = true;
23956 it->multibyte_p = STRING_MULTIBYTE (it->string);
23957 it->current.overlay_string_index = -1;
23958 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
23959 it->end_charpos = it->string_nchars = SCHARS (it->string);
23960 it->method = GET_FROM_STRING;
23961 it->stop_charpos = 0;
23962 it->prev_stop = 0;
23963 it->base_level_stop = 0;
23964 it->cmp_it.id = -1;
23965
23966
23967
23968 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
23969 it->paragraph_embedding = it->bidi_it.paragraph_dir;
23970 else
23971 it->paragraph_embedding = L2R;
23972
23973
23974 if (it->bidi_p)
23975 {
23976 it->bidi_it.string.lstring = it->string;
23977 it->bidi_it.string.s = NULL;
23978 it->bidi_it.string.schars = it->end_charpos;
23979 it->bidi_it.string.bufpos = IT_CHARPOS (*it);
23980 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
23981 it->bidi_it.string.unibyte = !it->multibyte_p;
23982 it->bidi_it.w = it->w;
23983 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
23984 }
23985 }
23986 else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
23987 {
23988 it->method = GET_FROM_STRETCH;
23989 it->object = prop;
23990 }
23991 #ifdef HAVE_WINDOW_SYSTEM
23992 else if (IMAGEP (prop))
23993 {
23994 it->what = IT_IMAGE;
23995 it->image_id = lookup_image (it->f, prop, it->face_id);
23996 it->method = GET_FROM_IMAGE;
23997 }
23998 #endif
23999 else
24000 {
24001 pop_it (it);
24002 return false;
24003 }
24004
24005 return true;
24006 }
24007
24008
24009
24010 static Lisp_Object
24011 get_it_property (struct it *it, Lisp_Object prop)
24012 {
24013 Lisp_Object position, object = it->object;
24014
24015 if (STRINGP (object))
24016 position = make_fixnum (IT_STRING_CHARPOS (*it));
24017 else if (BUFFERP (object))
24018 {
24019 position = make_fixnum (IT_CHARPOS (*it));
24020 object = it->window;
24021 }
24022 else
24023 return Qnil;
24024
24025 return Fget_char_property (position, prop, object);
24026 }
24027
24028
24029
24030
24031 static Lisp_Object
24032 get_line_prefix_it_property (struct it *it, Lisp_Object prop)
24033 {
24034 Lisp_Object prefix = get_it_property (it, prop);
24035
24036
24037
24038 if (NILP (prefix) && it->sp > 0 && STRINGP (it->object))
24039 return Fget_char_property (make_fixnum (IT_CHARPOS (*it)), prop,
24040 it->w->contents);
24041 return prefix;
24042 }
24043
24044
24045
24046 static void
24047 handle_line_prefix (struct it *it)
24048 {
24049 Lisp_Object prefix;
24050
24051 if (it->continuation_lines_width > 0)
24052 {
24053 prefix = get_line_prefix_it_property (it, Qwrap_prefix);
24054 if (NILP (prefix))
24055 prefix = Vwrap_prefix;
24056 }
24057 else
24058 {
24059 prefix = get_line_prefix_it_property (it, Qline_prefix);
24060 if (NILP (prefix))
24061 prefix = Vline_prefix;
24062 }
24063 if (! NILP (prefix) && push_prefix_prop (it, prefix))
24064 {
24065
24066
24067
24068 it->line_wrap = TRUNCATE;
24069 it->avoid_cursor_p = true;
24070 }
24071 }
24072
24073
24074
24075
24076
24077
24078
24079 static void
24080 unproduce_glyphs (struct it *it, int n)
24081 {
24082 struct glyph *glyph, *end;
24083
24084 eassert (it->glyph_row);
24085 eassert (it->glyph_row->reversed_p);
24086 eassert (it->area == TEXT_AREA);
24087 eassert (n <= it->glyph_row->used[TEXT_AREA]);
24088
24089 if (n > it->glyph_row->used[TEXT_AREA])
24090 n = it->glyph_row->used[TEXT_AREA];
24091 glyph = it->glyph_row->glyphs[TEXT_AREA] + n;
24092 end = it->glyph_row->glyphs[TEXT_AREA] + it->glyph_row->used[TEXT_AREA];
24093 for ( ; glyph < end; glyph++)
24094 glyph[-n] = *glyph;
24095 }
24096
24097
24098
24099 static void
24100 find_row_edges (struct it *it, struct glyph_row *row,
24101 ptrdiff_t min_pos, ptrdiff_t min_bpos,
24102 ptrdiff_t max_pos, ptrdiff_t max_bpos)
24103 {
24104
24105
24106
24107
24108
24109 if (min_pos <= ZV && min_pos < row->start.pos.charpos)
24110 SET_TEXT_POS (row->minpos, min_pos, min_bpos);
24111 else
24112
24113
24114
24115 row->minpos = row->start.pos;
24116 if (max_pos <= 0)
24117 {
24118 max_pos = CHARPOS (it->current.pos);
24119 max_bpos = BYTEPOS (it->current.pos);
24120 }
24121
24122
24123
24124
24125
24126
24127
24128
24129
24130
24131
24132
24133
24134
24135
24136
24137
24138 if (row->ends_at_zv_p)
24139 row->maxpos = it->current.pos;
24140 else if (row->used[TEXT_AREA])
24141 {
24142 bool seen_this_string = false;
24143 struct glyph_row *r1 = row - 1;
24144
24145
24146 if (STRINGP (it->object)
24147
24148 && row > it->w->desired_matrix->rows
24149
24150 && !r1->mode_line_p
24151
24152 && r1->ends_in_newline_from_string_p)
24153 {
24154 struct glyph *start, *end;
24155
24156
24157
24158
24159
24160 if (!r1->reversed_p)
24161 {
24162 start = r1->glyphs[TEXT_AREA];
24163 end = start + r1->used[TEXT_AREA];
24164
24165 while (end > start
24166 && NILP ((end - 1)->object)
24167 && (end - 1)->charpos <= 0)
24168 --end;
24169 if (end > start)
24170 {
24171 if (EQ ((end - 1)->object, it->object))
24172 seen_this_string = true;
24173 }
24174 else
24175
24176
24177
24178
24179
24180 seen_this_string = true;
24181 }
24182 else
24183 {
24184 end = r1->glyphs[TEXT_AREA] - 1;
24185 start = end + r1->used[TEXT_AREA];
24186 while (end < start
24187 && NILP ((end + 1)->object)
24188 && (end + 1)->charpos <= 0)
24189 ++end;
24190 if (end < start)
24191 {
24192 if (EQ ((end + 1)->object, it->object))
24193 seen_this_string = true;
24194 }
24195 else
24196 seen_this_string = true;
24197 }
24198 }
24199
24200
24201
24202 if (row->ends_in_newline_from_string_p && !seen_this_string)
24203 {
24204
24205
24206
24207
24208
24209
24210
24211
24212 if (CHARPOS (row->end.pos) > max_pos)
24213 inc_both (&max_pos, &max_bpos);
24214 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24215 }
24216 else if (CHARPOS (it->eol_pos) > 0)
24217 SET_TEXT_POS (row->maxpos,
24218 CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1);
24219 else if (row->continued_p)
24220 {
24221
24222
24223
24224
24225
24226
24227 if (IT_CHARPOS (*it) == max_pos && it->method != GET_FROM_BUFFER)
24228 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24229 else
24230 {
24231 inc_both (&max_pos, &max_bpos);
24232 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24233 }
24234 }
24235 else if (row->truncated_on_right_p)
24236
24237
24238
24239 row->maxpos = it->current.pos;
24240 else if (max_pos == min_pos && it->method != GET_FROM_BUFFER)
24241
24242 row->maxpos = row->minpos;
24243 else
24244 emacs_abort ();
24245 }
24246 else
24247 row->maxpos = it->current.pos;
24248 }
24249
24250
24251
24252 static ptrdiff_t
24253 display_count_lines_logically (ptrdiff_t start_byte, ptrdiff_t limit_byte,
24254 ptrdiff_t count, ptrdiff_t *byte_pos_ptr)
24255 {
24256 if (!display_line_numbers_widen || (BEGV == BEG && ZV == Z))
24257 return display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24258
24259 ptrdiff_t val;
24260 specpdl_ref pdl_count = SPECPDL_INDEX ();
24261 record_unwind_protect (save_restriction_restore, save_restriction_save ());
24262 labeled_restrictions_remove_in_current_buffer ();
24263 Fwiden ();
24264 val = display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24265 unbind_to (pdl_count, Qnil);
24266 return val;
24267 }
24268
24269
24270
24271 static ptrdiff_t
24272 display_count_lines_visually (struct it *it)
24273 {
24274 struct it tem_it;
24275 ptrdiff_t to;
24276 struct text_pos from;
24277
24278
24279
24280
24281
24282
24283 if (it->lnum_bytepos > 0)
24284 return it->lnum + 1;
24285 else
24286 {
24287 specpdl_ref count = SPECPDL_INDEX ();
24288
24289 if (IT_CHARPOS (*it) <= PT)
24290 {
24291 from = it->current.pos;
24292 to = PT;
24293 }
24294 else
24295 {
24296 SET_TEXT_POS (from, PT, PT_BYTE);
24297 to = IT_CHARPOS (*it);
24298 }
24299
24300
24301
24302 specbind (Qdisplay_line_numbers, Qrelative);
24303 start_display (&tem_it, it->w, from);
24304
24305
24306
24307
24308 move_it_to (&tem_it, to, -1,
24309 tem_it.last_visible_y
24310 + (SCROLL_LIMIT + 10) * FRAME_LINE_HEIGHT (tem_it.f),
24311 -1, MOVE_TO_POS | MOVE_TO_Y);
24312 unbind_to (count, Qnil);
24313 return IT_CHARPOS (*it) <= PT ? -tem_it.vpos : tem_it.vpos;
24314 }
24315 }
24316
24317
24318
24319
24320 static void
24321 maybe_produce_line_number (struct it *it)
24322 {
24323 ptrdiff_t last_line = it->lnum;
24324 ptrdiff_t start_from, bytepos;
24325 ptrdiff_t this_line;
24326 bool first_time = false;
24327 ptrdiff_t beg_byte;
24328 ptrdiff_t z_byte;
24329 bool line_numbers_wide;
24330 void *itdata = bidi_shelve_cache ();
24331
24332 if (display_line_numbers_offset
24333 && !display_line_numbers_widen
24334 && !EQ (Vdisplay_line_numbers, Qvisual)
24335 && !EQ (Vdisplay_line_numbers, Qrelative))
24336 line_numbers_wide = true;
24337 else
24338 line_numbers_wide = display_line_numbers_widen;
24339
24340 beg_byte = line_numbers_wide ? BEG_BYTE : BEGV_BYTE;
24341 z_byte = line_numbers_wide ? Z_BYTE : ZV_BYTE;
24342
24343 if (EQ (Vdisplay_line_numbers, Qvisual))
24344 this_line = display_count_lines_visually (it);
24345 else
24346 {
24347 if (!last_line)
24348 {
24349
24350 if (it->w->base_line_number > 0
24351 && it->w->base_line_pos > 0
24352 && it->w->base_line_pos <= IT_CHARPOS (*it)
24353
24354
24355
24356
24357 && !(line_numbers_wide
24358 && (BEG_BYTE != BEGV_BYTE || Z_BYTE != ZV_BYTE))
24359 && !current_buffer->clip_changed)
24360 {
24361 start_from = CHAR_TO_BYTE (it->w->base_line_pos);
24362 last_line = it->w->base_line_number - 1;
24363 }
24364 else
24365 start_from = beg_byte;
24366 if (!it->lnum_bytepos)
24367 first_time = true;
24368 }
24369 else
24370 start_from = it->lnum_bytepos;
24371
24372
24373
24374
24375 if (!(beg_byte <= start_from && start_from <= z_byte))
24376 {
24377 last_line = 0;
24378 start_from = beg_byte;
24379 }
24380
24381 this_line =
24382 last_line + display_count_lines_logically (start_from,
24383 IT_BYTEPOS (*it),
24384 IT_CHARPOS (*it), &bytepos);
24385 eassert (this_line > 0 || (this_line == 0 && start_from == beg_byte));
24386 eassert (bytepos == IT_BYTEPOS (*it));
24387 }
24388
24389
24390 if (this_line != last_line || !it->lnum_bytepos)
24391 {
24392 it->lnum = this_line;
24393 it->lnum_bytepos = IT_BYTEPOS (*it);
24394 }
24395
24396
24397 struct it tem_it;
24398 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
24399 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
24400 ptrdiff_t lnum_offset = -1;
24401 int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID);
24402 int current_lnum_face_id
24403 = merge_faces (it->w, Qline_number_current_line, 0, DEFAULT_FACE_ID);
24404
24405
24406 bool save_free_realized_faces = inhibit_free_realized_faces;
24407 inhibit_free_realized_faces = true;
24408
24409 if ((EQ (Vdisplay_line_numbers, Qrelative)
24410 || EQ (Vdisplay_line_numbers, Qvisual)
24411 || lnum_face_id != current_lnum_face_id)
24412 && !it->pt_lnum)
24413 {
24414 ptrdiff_t ignored;
24415 if (PT_BYTE > it->lnum_bytepos && !EQ (Vdisplay_line_numbers, Qvisual))
24416 it->pt_lnum =
24417 this_line + display_count_lines_logically (it->lnum_bytepos, PT_BYTE,
24418 PT, &ignored);
24419 else
24420 it->pt_lnum = display_count_lines_logically (beg_byte, PT_BYTE, PT,
24421 &ignored);
24422 }
24423
24424 if (!it->lnum_width)
24425 {
24426 if (FIXNATP (Vdisplay_line_numbers_width))
24427 it->lnum_width = XFIXNAT (Vdisplay_line_numbers_width);
24428
24429
24430
24431 ptrdiff_t max_lnum;
24432
24433 if (NILP (Vdisplay_line_numbers_current_absolute)
24434 && (EQ (Vdisplay_line_numbers, Qrelative)
24435 || EQ (Vdisplay_line_numbers, Qvisual)))
24436
24437
24438 max_lnum = it->w->desired_matrix->nrows - 2;
24439 else if (EQ (Vdisplay_line_numbers, Qvisual))
24440 max_lnum = it->pt_lnum + it->w->desired_matrix->nrows - 1;
24441 else
24442 max_lnum = this_line + it->w->desired_matrix->nrows - 1 - it->vpos;
24443 max_lnum = max (1, max_lnum);
24444 it->lnum_width = max (it->lnum_width, log10 (max_lnum) + 1);
24445 eassert (it->lnum_width > 0);
24446 }
24447 if (EQ (Vdisplay_line_numbers, Qrelative))
24448 lnum_offset = it->pt_lnum;
24449 else if (EQ (Vdisplay_line_numbers, Qvisual))
24450 lnum_offset = 0;
24451 else if (display_line_numbers_offset)
24452 lnum_offset -= display_line_numbers_offset;
24453
24454
24455
24456 ptrdiff_t lnum_to_display = eabs (this_line - lnum_offset);
24457 if ((EQ (Vdisplay_line_numbers, Qrelative)
24458 || EQ (Vdisplay_line_numbers, Qvisual))
24459 && lnum_to_display == 0
24460 && !NILP (Vdisplay_line_numbers_current_absolute))
24461 lnum_to_display = it->pt_lnum + 1;
24462
24463
24464
24465
24466
24467 pint2str (lnum_buf, it->lnum_width + 1, lnum_to_display);
24468 strcat (lnum_buf, " ");
24469
24470
24471 init_iterator (&tem_it, it->w, -1, -1, &scratch_glyph_row,
24472
24473 DEFAULT_FACE_ID);
24474 scratch_glyph_row.reversed_p = false;
24475 scratch_glyph_row.used[TEXT_AREA] = 0;
24476 SET_TEXT_POS (tem_it.position, 0, 0);
24477 tem_it.avoid_cursor_p = true;
24478 tem_it.bidi_p = true;
24479 tem_it.bidi_it.type = WEAK_EN;
24480
24481
24482
24483 tem_it.bidi_it.resolved_level = 2;
24484
24485
24486
24487 int width_limit =
24488 tem_it.last_visible_x - tem_it.first_visible_x
24489 - 3 * FRAME_COLUMN_WIDTH (it->f);
24490
24491 tem_it.face_id = lnum_face_id;
24492
24493
24494 if (lnum_face_id != current_lnum_face_id
24495 && (EQ (Vdisplay_line_numbers, Qvisual)
24496 ? this_line == 0
24497 : this_line == it->pt_lnum)
24498 && it->what != IT_EOB)
24499 tem_it.face_id = current_lnum_face_id;
24500 else if (!beyond_zv)
24501 {
24502 if (display_line_numbers_major_tick > 0
24503 && (lnum_to_display % display_line_numbers_major_tick == 0))
24504 tem_it.face_id = merge_faces (it->w, Qline_number_major_tick,
24505 0, DEFAULT_FACE_ID);
24506 else if (display_line_numbers_minor_tick > 0
24507 && (lnum_to_display % display_line_numbers_minor_tick == 0))
24508 tem_it.face_id = merge_faces (it->w, Qline_number_minor_tick,
24509 0, DEFAULT_FACE_ID);
24510 }
24511
24512
24513 for (const char *p = lnum_buf; *p; p++)
24514 {
24515
24516
24517 if (beyond_zv
24518
24519 || (!EQ (Vdisplay_line_numbers, Qvisual)
24520 && (it->continuation_lines_width > 0
24521 || (this_line == last_line && !first_time))))
24522 tem_it.c = tem_it.char_to_display = ' ';
24523 else
24524 tem_it.c = tem_it.char_to_display = *p;
24525 tem_it.len = 1;
24526
24527 SET_TEXT_POS (tem_it.position, -1, -1);
24528 PRODUCE_GLYPHS (&tem_it);
24529
24530
24531
24532 if (tem_it.current_x >= width_limit)
24533 {
24534 it->lnum_width = 0;
24535 it->lnum_pixel_width = 0;
24536 bidi_unshelve_cache (itdata, false);
24537 inhibit_free_realized_faces = save_free_realized_faces;
24538 return;
24539 }
24540 }
24541
24542 inhibit_free_realized_faces = save_free_realized_faces;
24543
24544
24545 it->lnum_pixel_width = tem_it.current_x;
24546
24547 struct glyph *g = scratch_glyph_row.glyphs[TEXT_AREA];
24548 struct glyph *e = g + scratch_glyph_row.used[TEXT_AREA];
24549 struct glyph *p = it->glyph_row ? it->glyph_row->glyphs[TEXT_AREA] : NULL;
24550 short *u = it->glyph_row ? &it->glyph_row->used[TEXT_AREA] : NULL;
24551
24552 eassert (it->glyph_row == NULL || it->glyph_row->used[TEXT_AREA] == 0);
24553
24554 for ( ; g < e; g++)
24555 {
24556 it->current_x += g->pixel_width;
24557
24558
24559
24560 if (it->current_x > it->first_visible_x)
24561 it->hpos++;
24562 if (p)
24563 {
24564 *p++ = *g;
24565 (*u)++;
24566 }
24567 }
24568
24569
24570
24571
24572 if (!beyond_zv)
24573 {
24574 if (it->glyph_row)
24575 {
24576 struct glyph_row *row = it->glyph_row;
24577
24578 it->max_ascent = max (row->ascent, tem_it.max_ascent);
24579 it->max_descent = max (row->height - row->ascent, tem_it.max_descent);
24580 it->max_phys_ascent = max (row->phys_ascent, tem_it.max_phys_ascent);
24581 it->max_phys_descent = max (row->phys_height - row->phys_ascent,
24582 tem_it.max_phys_descent);
24583 }
24584 else
24585 {
24586 it->max_ascent = max (it->max_ascent, tem_it.max_ascent);
24587 it->max_descent = max (it->max_descent, tem_it.max_descent);
24588 it->max_phys_ascent = max (it->max_phys_ascent,
24589 tem_it.max_phys_ascent);
24590 it->max_phys_descent = max (it->max_phys_descent,
24591 tem_it.max_phys_descent);
24592 }
24593 }
24594
24595 it->line_number_produced_p = true;
24596
24597 bidi_unshelve_cache (itdata, false);
24598 }
24599
24600
24601
24602 static bool
24603 should_produce_line_number (struct it *it)
24604 {
24605 if (NILP (Vdisplay_line_numbers))
24606 return false;
24607
24608
24609 if (MINI_WINDOW_P (it->w))
24610 return false;
24611
24612 #ifdef HAVE_WINDOW_SYSTEM
24613
24614 if (FRAME_TOOLTIP_P (XFRAME (WINDOW_FRAME (it->w))))
24615 return false;
24616 #endif
24617
24618
24619
24620
24621
24622 Lisp_Object val = Fget_char_property (make_fixnum (IT_CHARPOS (*it)),
24623 Qdisplay_line_numbers_disable,
24624 it->window);
24625
24626
24627
24628 if (NILP (val) && IT_CHARPOS (*it) >= ZV)
24629 val = disable_line_numbers_overlay_at_eob ();
24630 return NILP (val) ? true : false;
24631 }
24632
24633
24634
24635
24636
24637 static bool
24638 row_text_area_empty (struct glyph_row *row)
24639 {
24640 if (!row->reversed_p)
24641 {
24642 for (struct glyph *g = row->glyphs[TEXT_AREA];
24643 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
24644 g++)
24645 if (!NILP (g->object) || g->charpos > 0)
24646 return false;
24647 }
24648 else
24649 {
24650 for (struct glyph *g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
24651 g > row->glyphs[TEXT_AREA];
24652 g--)
24653 if (!NILP ((g - 1)->object) || (g - 1)->charpos > 0)
24654 return false;
24655 }
24656
24657 return true;
24658 }
24659
24660
24661
24662
24663
24664
24665
24666
24667 static bool
24668 display_line (struct it *it, int cursor_vpos)
24669 {
24670 struct glyph_row *row = it->glyph_row;
24671 Lisp_Object overlay_arrow_string;
24672 struct it wrap_it;
24673 void *wrap_data = NULL;
24674 bool may_wrap = false;
24675 int wrap_x UNINIT;
24676 int wrap_row_used = -1;
24677 int wrap_row_ascent UNINIT, wrap_row_height UNINIT;
24678 int wrap_row_phys_ascent UNINIT, wrap_row_phys_height UNINIT;
24679 int wrap_row_extra_line_spacing UNINIT;
24680 ptrdiff_t wrap_row_min_pos UNINIT, wrap_row_min_bpos UNINIT;
24681 ptrdiff_t wrap_row_max_pos UNINIT, wrap_row_max_bpos UNINIT;
24682 int cvpos;
24683 ptrdiff_t min_pos = ZV + 1, max_pos = 0;
24684 ptrdiff_t min_bpos UNINIT, max_bpos UNINIT;
24685 bool pending_handle_line_prefix = false;
24686 int tab_line = window_wants_tab_line (it->w);
24687 int header_line = window_wants_header_line (it->w);
24688 bool hscroll_this_line = (cursor_vpos >= 0
24689 && it->vpos == cursor_vpos - tab_line - header_line
24690 && hscrolling_current_line_p (it->w));
24691 int first_visible_x = it->first_visible_x;
24692 int last_visible_x = it->last_visible_x;
24693 int x_incr = 0;
24694
24695
24696 eassert (it->hpos == 0 && it->current_x == 0);
24697
24698 if (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
24699 >= it->w->desired_matrix->nrows)
24700 {
24701 it->w->nrows_scale_factor++;
24702 it->f->fonts_changed = true;
24703 return false;
24704 }
24705
24706
24707 prepare_desired_row (it->w, row, false);
24708
24709 row->y = it->current_y;
24710 row->start = it->start;
24711 row->continuation_lines_width = it->continuation_lines_width;
24712 row->displays_text_p = true;
24713 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
24714 it->starts_in_middle_of_char_p = false;
24715 it->stretch_adjust = 0;
24716 it->line_number_produced_p = false;
24717
24718
24719
24720
24721 if (hscroll_this_line)
24722 x_incr =
24723 (window_hscroll_limited (it->w, it->f) - it->w->min_hscroll)
24724 * FRAME_COLUMN_WIDTH (it->f);
24725
24726 bool line_number_needed = should_produce_line_number (it);
24727
24728
24729
24730
24731 if (it->current_x < it->first_visible_x + x_incr)
24732 {
24733 enum move_it_result move_result;
24734
24735 this_line_min_pos = row->start.pos;
24736 if (hscroll_this_line)
24737 {
24738 it->first_visible_x += x_incr;
24739 it->last_visible_x += x_incr;
24740 }
24741 if (current_buffer->long_line_optimizations_p
24742 && it->line_wrap == TRUNCATE
24743 && window_hscroll_limited (it->w, it->f) > large_hscroll_threshold)
24744 {
24745
24746
24747
24748
24749 ptrdiff_t chars_to_skip =
24750 it->first_visible_x / FRAME_COLUMN_WIDTH (it->f);
24751 move_result = fast_move_it_horizontally (it, chars_to_skip);
24752
24753 if (move_result == MOVE_X_REACHED)
24754 it->current_x = it->first_visible_x;
24755 else
24756 it->current_x = it->first_visible_x - FRAME_COLUMN_WIDTH (it->f);
24757 }
24758 else
24759 move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
24760 MOVE_TO_POS | MOVE_TO_X);
24761
24762
24763
24764
24765
24766
24767 if (it->current_x < it->first_visible_x
24768 && (move_result == MOVE_NEWLINE_OR_CR
24769 || move_result == MOVE_POS_MATCH_OR_ZV))
24770 it->current_x = it->first_visible_x;
24771
24772
24773
24774 it->line_number_produced_p = false;
24775
24776
24777
24778
24779
24780
24781
24782
24783 min_pos = CHARPOS (this_line_min_pos);
24784 min_bpos = BYTEPOS (this_line_min_pos);
24785
24786
24787 if (line_number_needed)
24788 maybe_produce_line_number (it);
24789 }
24790 else if (it->area == TEXT_AREA)
24791 {
24792
24793 if (line_number_needed)
24794 maybe_produce_line_number (it);
24795
24796
24797
24798 handle_line_prefix (it);
24799 }
24800 else
24801 {
24802
24803
24804
24805
24806
24807
24808
24809 pending_handle_line_prefix = true;
24810 }
24811
24812
24813
24814 row->ascent = it->max_ascent;
24815 row->height = it->max_ascent + it->max_descent;
24816 row->phys_ascent = it->max_phys_ascent;
24817 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
24818 row->extra_line_spacing = it->max_extra_line_spacing;
24819
24820
24821 #define RECORD_MAX_MIN_POS(IT) \
24822 do \
24823 { \
24824 bool composition_p \
24825 = !STRINGP ((IT)->string) && ((IT)->what == IT_COMPOSITION); \
24826 ptrdiff_t current_pos = \
24827 composition_p ? (IT)->cmp_it.charpos \
24828 : IT_CHARPOS (*(IT)); \
24829 ptrdiff_t current_bpos = \
24830 composition_p ? CHAR_TO_BYTE (current_pos) \
24831 : IT_BYTEPOS (*(IT)); \
24832 if (current_pos < min_pos) \
24833 { \
24834 min_pos = current_pos; \
24835 min_bpos = current_bpos; \
24836 } \
24837 if (IT_CHARPOS (*it) > max_pos) \
24838 { \
24839 max_pos = IT_CHARPOS (*it); \
24840 max_bpos = IT_BYTEPOS (*it); \
24841 } \
24842 } \
24843 while (false)
24844
24845
24846
24847 while (true)
24848 {
24849 int n_glyphs_before, hpos_before, x_before;
24850 int x, nglyphs;
24851 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
24852
24853
24854
24855 if (!get_next_display_element (it))
24856 {
24857 bool row_has_glyphs = false;
24858
24859
24860
24861
24862 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
24863 row->exact_window_width_line_p = true;
24864 else if ((append_space_for_newline (it, true)
24865 && row->used[TEXT_AREA] == 1)
24866 || row->used[TEXT_AREA] == 0
24867 || (row_has_glyphs = row_text_area_empty (row)))
24868 {
24869 row->glyphs[TEXT_AREA]->charpos = -1;
24870
24871
24872 if (!row_has_glyphs)
24873 row->displays_text_p = false;
24874
24875 if (!NILP (BVAR (XBUFFER (it->w->contents), indicate_empty_lines))
24876 && (!MINI_WINDOW_P (it->w)))
24877 row->indicate_empty_line_p = true;
24878 }
24879
24880 it->continuation_lines_width = 0;
24881
24882
24883
24884
24885 it->font_height = Qnil;
24886 it->voffset = 0;
24887 row->ends_at_zv_p = true;
24888
24889
24890
24891
24892
24893
24894
24895
24896 if (row->reversed_p
24897 || lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
24898 != DEFAULT_FACE_ID)
24899 extend_face_to_end_of_line (it);
24900 break;
24901 }
24902
24903
24904
24905 n_glyphs_before = row->used[TEXT_AREA];
24906 x = it->current_x;
24907
24908
24909
24910 if (it->line_wrap != TRUNCATE)
24911 {
24912 ascent = it->max_ascent;
24913 descent = it->max_descent;
24914 phys_ascent = it->max_phys_ascent;
24915 phys_descent = it->max_phys_descent;
24916
24917 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
24918 {
24919 bool next_may_wrap = may_wrap;
24920
24921 if (char_can_wrap_after (it))
24922 next_may_wrap = true;
24923 else
24924 next_may_wrap = false;
24925
24926 if (may_wrap && char_can_wrap_before (it))
24927 {
24928 SAVE_IT (wrap_it, *it, wrap_data);
24929 wrap_x = x;
24930 wrap_row_used = row->used[TEXT_AREA];
24931 wrap_row_ascent = row->ascent;
24932 wrap_row_height = row->height;
24933 wrap_row_phys_ascent = row->phys_ascent;
24934 wrap_row_phys_height = row->phys_height;
24935 wrap_row_extra_line_spacing = row->extra_line_spacing;
24936 wrap_row_min_pos = min_pos;
24937 wrap_row_min_bpos = min_bpos;
24938 wrap_row_max_pos = max_pos;
24939 wrap_row_max_bpos = max_bpos;
24940 }
24941
24942 may_wrap = next_may_wrap;
24943 }
24944 }
24945
24946 PRODUCE_GLYPHS (it);
24947
24948
24949
24950 if (it->area != TEXT_AREA)
24951 {
24952 row->ascent = max (row->ascent, it->max_ascent);
24953 row->height = max (row->height, it->max_ascent + it->max_descent);
24954 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
24955 row->phys_height = max (row->phys_height,
24956 it->max_phys_ascent + it->max_phys_descent);
24957 row->extra_line_spacing = max (row->extra_line_spacing,
24958 it->max_extra_line_spacing);
24959 set_iterator_to_next (it, true);
24960
24961
24962
24963 if (it->area == TEXT_AREA && pending_handle_line_prefix)
24964 {
24965
24966 if (line_number_needed)
24967 maybe_produce_line_number (it);
24968
24969 pending_handle_line_prefix = false;
24970 handle_line_prefix (it);
24971 }
24972 continue;
24973 }
24974
24975
24976
24977
24978
24979
24980
24981
24982
24983
24984 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
24985 hpos_before = it->hpos;
24986 x_before = x;
24987
24988 if (
24989 nglyphs > 0
24990
24991 && it->current_x < it->last_visible_x)
24992 {
24993 it->hpos += nglyphs;
24994 row->ascent = max (row->ascent, it->max_ascent);
24995 row->height = max (row->height, it->max_ascent + it->max_descent);
24996 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
24997 row->phys_height = max (row->phys_height,
24998 it->max_phys_ascent + it->max_phys_descent);
24999 row->extra_line_spacing = max (row->extra_line_spacing,
25000 it->max_extra_line_spacing);
25001 if (it->current_x - it->pixel_width < it->first_visible_x
25002
25003
25004
25005 && !line_number_needed
25006
25007
25008
25009
25010 && !row->reversed_p)
25011 row->x = x - it->first_visible_x;
25012
25013
25014 if (it->bidi_p)
25015 RECORD_MAX_MIN_POS (it);
25016 }
25017 else
25018 {
25019 int i, new_x;
25020 struct glyph *glyph;
25021
25022 for (i = 0; i < nglyphs; ++i, x = new_x)
25023 {
25024
25025
25026
25027 if (!row->reversed_p)
25028 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
25029 else
25030 glyph = row->glyphs[TEXT_AREA] + nglyphs - 1 - i;
25031 new_x = x + glyph->pixel_width;
25032
25033 if (
25034 it->line_wrap != TRUNCATE
25035 && (
25036 new_x > it->last_visible_x
25037
25038 || (new_x == it->last_visible_x
25039 && FRAME_WINDOW_P (it->f)
25040 && (row->reversed_p
25041 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25042 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
25043 {
25044
25045
25046 if (it->hpos == 0
25047 || (new_x == it->last_visible_x
25048 && FRAME_WINDOW_P (it->f)
25049 && (row->reversed_p
25050 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25051 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
25052 {
25053
25054
25055
25056
25057 row->continued_p = true;
25058 it->current_x = new_x;
25059 it->continuation_lines_width += new_x;
25060 ++it->hpos;
25061 if (i == nglyphs - 1)
25062 {
25063
25064
25065 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
25066 && wrap_row_used > 0
25067
25068
25069
25070
25071
25072
25073
25074
25075
25076
25077 && (!may_wrap || !char_can_wrap_before (it)))
25078 goto back_to_wrap;
25079
25080
25081
25082
25083 if (it->bidi_p)
25084 RECORD_MAX_MIN_POS (it);
25085 set_iterator_to_next (it, true);
25086 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25087 {
25088 if (!get_next_display_element (it))
25089 {
25090 row->exact_window_width_line_p = true;
25091 it->continuation_lines_width = 0;
25092 it->font_height = Qnil;
25093 it->voffset = 0;
25094 row->continued_p = false;
25095 row->ends_at_zv_p = true;
25096 }
25097 else if (ITERATOR_AT_END_OF_LINE_P (it))
25098 {
25099 row->continued_p = false;
25100 row->exact_window_width_line_p = true;
25101 }
25102
25103
25104 else if (wrap_row_used > 0
25105
25106
25107
25108
25109
25110
25111
25112
25113
25114 && (!may_wrap || !char_can_wrap_before (it)))
25115 goto back_to_wrap;
25116
25117 }
25118 }
25119 else if (it->bidi_p)
25120 RECORD_MAX_MIN_POS (it);
25121 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25122 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25123 extend_face_to_end_of_line (it);
25124 }
25125 else if (CHAR_GLYPH_PADDING_P (*glyph)
25126 && !FRAME_WINDOW_P (it->f))
25127 {
25128
25129
25130
25131 if (row->reversed_p)
25132 unproduce_glyphs (it, row->used[TEXT_AREA]
25133 - n_glyphs_before);
25134 row->used[TEXT_AREA] = n_glyphs_before;
25135
25136
25137
25138 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
25139 < row->glyphs[1 + TEXT_AREA])
25140 produce_special_glyphs (it, IT_CONTINUATION);
25141
25142 row->continued_p = true;
25143 it->current_x = x_before;
25144 it->continuation_lines_width += x_before;
25145
25146
25147
25148 it->max_ascent = ascent;
25149 it->max_descent = descent;
25150 it->max_phys_ascent = phys_ascent;
25151 it->max_phys_descent = phys_descent;
25152 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25153 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25154 extend_face_to_end_of_line (it);
25155 }
25156 else if (wrap_row_used > 0)
25157 {
25158 back_to_wrap:
25159 if (row->reversed_p)
25160 unproduce_glyphs (it,
25161 row->used[TEXT_AREA] - wrap_row_used);
25162 RESTORE_IT (it, &wrap_it, wrap_data);
25163 it->continuation_lines_width += wrap_x;
25164 row->used[TEXT_AREA] = wrap_row_used;
25165 row->ascent = wrap_row_ascent;
25166 row->height = wrap_row_height;
25167 row->phys_ascent = wrap_row_phys_ascent;
25168 row->phys_height = wrap_row_phys_height;
25169 row->extra_line_spacing = wrap_row_extra_line_spacing;
25170 min_pos = wrap_row_min_pos;
25171 min_bpos = wrap_row_min_bpos;
25172 max_pos = wrap_row_max_pos;
25173 max_bpos = wrap_row_max_bpos;
25174 row->continued_p = true;
25175 row->ends_at_zv_p = false;
25176 row->exact_window_width_line_p = false;
25177
25178
25179
25180 extend_face_to_end_of_line (it);
25181 }
25182 else if ((it->what == IT_CHARACTER
25183 || it->what == IT_STRETCH
25184 || it->what == IT_COMPOSITION)
25185 && it->c == '\t' && FRAME_WINDOW_P (it->f))
25186 {
25187
25188
25189
25190
25191
25192 if ((row->reversed_p
25193 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25194 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25195 produce_special_glyphs (it, IT_CONTINUATION);
25196 it->continuation_lines_width += it->last_visible_x;
25197 row->ends_in_middle_of_char_p = true;
25198 row->continued_p = true;
25199 glyph->pixel_width = it->last_visible_x - x;
25200 it->starts_in_middle_of_char_p = true;
25201 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25202 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25203 extend_face_to_end_of_line (it);
25204 }
25205 else
25206 {
25207
25208
25209
25210 if (row->reversed_p)
25211 unproduce_glyphs (it, row->used[TEXT_AREA]
25212 - (n_glyphs_before + i));
25213 row->used[TEXT_AREA] = n_glyphs_before + i;
25214
25215
25216 it->current_x = x_before;
25217 it->continuation_lines_width += x;
25218 if (!FRAME_WINDOW_P (it->f)
25219 || (row->reversed_p
25220 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25221 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25222 produce_special_glyphs (it, IT_CONTINUATION);
25223 row->continued_p = true;
25224
25225 extend_face_to_end_of_line (it);
25226
25227 if (nglyphs > 1 && i > 0)
25228 {
25229 row->ends_in_middle_of_char_p = true;
25230 it->starts_in_middle_of_char_p = true;
25231 }
25232
25233
25234
25235 it->max_ascent = ascent;
25236 it->max_descent = descent;
25237 it->max_phys_ascent = phys_ascent;
25238 it->max_phys_descent = phys_descent;
25239 }
25240
25241 break;
25242 }
25243 else if (new_x > it->first_visible_x)
25244 {
25245
25246 ++it->hpos;
25247
25248
25249
25250
25251 if (it->bidi_p)
25252 RECORD_MAX_MIN_POS (it);
25253
25254 if (x < it->first_visible_x && !row->reversed_p
25255 && !line_number_needed)
25256
25257
25258
25259
25260
25261
25262 row->x = x - it->first_visible_x;
25263
25264
25265
25266
25267
25268
25269 if (row->reversed_p
25270 && new_x > it->last_visible_x
25271 && !line_number_needed
25272 && !(it->line_wrap == TRUNCATE
25273 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
25274 {
25275 eassert (FRAME_WINDOW_P (it->f));
25276 row->x = it->last_visible_x - new_x;
25277 }
25278 }
25279 else
25280 {
25281
25282
25283
25284
25285
25286 eassert (it->first_visible_x <= it->last_visible_x);
25287 }
25288 }
25289
25290
25291 if (it->bidi_p && nglyphs == 0)
25292 RECORD_MAX_MIN_POS (it);
25293
25294 row->ascent = max (row->ascent, it->max_ascent);
25295 row->height = max (row->height, it->max_ascent + it->max_descent);
25296 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25297 row->phys_height = max (row->phys_height,
25298 it->max_phys_ascent + it->max_phys_descent);
25299 row->extra_line_spacing = max (row->extra_line_spacing,
25300 it->max_extra_line_spacing);
25301
25302
25303 if (row->continued_p || row->ends_at_zv_p)
25304 break;
25305 }
25306
25307 at_end_of_line:
25308
25309
25310
25311 if (ITERATOR_AT_END_OF_LINE_P (it))
25312 {
25313 int used_before = row->used[TEXT_AREA];
25314
25315 row->ends_in_newline_from_string_p = STRINGP (it->object);
25316
25317
25318
25319 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25320 append_space_for_newline (it, false);
25321
25322
25323 extend_face_to_end_of_line (it);
25324
25325
25326 if (used_before == 0)
25327 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
25328
25329
25330
25331 it->eol_pos = it->current.pos;
25332
25333
25334 set_iterator_to_next (it, true);
25335 it->continuation_lines_width = 0;
25336 break;
25337 }
25338
25339
25340
25341
25342
25343
25344
25345
25346 bool overwide_wrap_prefix =
25347 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
25348 && it->sp > 0 && it->method == GET_FROM_STRETCH
25349 && it->current_x >= it->last_visible_x
25350 && it->continuation_lines_width > 0
25351 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
25352
25353
25354
25355 if (!overwide_wrap_prefix)
25356 set_iterator_to_next (it, true);
25357
25358
25359
25360 if (it->line_wrap == TRUNCATE
25361 && ((FRAME_WINDOW_P (it->f)
25362
25363
25364
25365
25366 && ((row->reversed_p
25367 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25368 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))
25369 || it->what == IT_IMAGE))
25370 ? (it->current_x >= it->last_visible_x)
25371 : (it->current_x > it->last_visible_x)))
25372 {
25373
25374 if (!FRAME_WINDOW_P (it->f)
25375 || (row->reversed_p
25376 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25377 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25378 {
25379 int i, n;
25380
25381 if (!row->reversed_p)
25382 {
25383 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
25384 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25385 break;
25386 }
25387 else
25388 {
25389 for (i = 0; i < row->used[TEXT_AREA]; i++)
25390 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25391 break;
25392
25393
25394
25395
25396
25397 unproduce_glyphs (it, i + 1);
25398
25399 i = row->used[TEXT_AREA] - (i + 1);
25400 }
25401
25402
25403
25404
25405 if (it->current_x > it->last_visible_x)
25406 {
25407 it->current_x = x_before;
25408 if (!FRAME_WINDOW_P (it->f))
25409 {
25410 for (n = row->used[TEXT_AREA]; i < n; ++i)
25411 {
25412 row->used[TEXT_AREA] = i;
25413 produce_special_glyphs (it, IT_TRUNCATION);
25414 }
25415 }
25416 else
25417 {
25418 row->used[TEXT_AREA] = i;
25419 produce_special_glyphs (it, IT_TRUNCATION);
25420 }
25421 it->hpos = hpos_before;
25422 }
25423 }
25424 else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25425 {
25426
25427 if (!get_next_display_element (it))
25428 {
25429 it->continuation_lines_width = 0;
25430 it->font_height = Qnil;
25431 it->voffset = 0;
25432 row->ends_at_zv_p = true;
25433 row->exact_window_width_line_p = true;
25434 break;
25435 }
25436 if (ITERATOR_AT_END_OF_LINE_P (it))
25437 {
25438 row->exact_window_width_line_p = true;
25439 goto at_end_of_line;
25440 }
25441 it->current_x = x_before;
25442 it->hpos = hpos_before;
25443 }
25444
25445 row->truncated_on_right_p = true;
25446 it->continuation_lines_width = 0;
25447 reseat_at_next_visible_line_start (it, false);
25448
25449
25450
25451
25452 if (IT_BYTEPOS (*it) > BEG_BYTE)
25453 row->ends_at_zv_p =
25454 IT_BYTEPOS (*it) >= ZV_BYTE
25455 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n');
25456 else
25457 row->ends_at_zv_p = false;
25458 break;
25459 }
25460 }
25461
25462 if (wrap_data)
25463 bidi_unshelve_cache (wrap_data, true);
25464
25465
25466
25467 if (it->first_visible_x
25468 && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
25469 {
25470 if (!FRAME_WINDOW_P (it->f)
25471 || (((row->reversed_p
25472 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
25473 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
25474
25475
25476 && row->glyphs[TEXT_AREA]->type != IMAGE_GLYPH))
25477 insert_left_trunc_glyphs (it);
25478 row->truncated_on_left_p = true;
25479 }
25480
25481
25482
25483
25484
25485
25486 row->end = it->current;
25487 if (!it->bidi_p)
25488 {
25489 row->minpos = row->start.pos;
25490 row->maxpos = row->end.pos;
25491 }
25492 else
25493 {
25494
25495
25496
25497
25498 find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos);
25499 }
25500
25501
25502
25503
25504
25505 if ((MATRIX_ROW_DISPLAYS_TEXT_P (row) || !overlay_arrow_seen)
25506 && (overlay_arrow_string = overlay_arrow_at_row (it, row),
25507 !NILP (overlay_arrow_string)))
25508 {
25509
25510 if (STRINGP (overlay_arrow_string))
25511 {
25512 struct glyph_row *arrow_row
25513 = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
25514 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
25515 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
25516 struct glyph *p = row->glyphs[TEXT_AREA];
25517 struct glyph *p2, *end;
25518
25519
25520 while (glyph < arrow_end)
25521 *p++ = *glyph++;
25522
25523
25524 p2 = p;
25525 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
25526 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
25527 ++p2;
25528 if (p2 > p)
25529 {
25530 while (p2 < end)
25531 *p++ = *p2++;
25532 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
25533 }
25534 }
25535 else
25536 {
25537 eassert (FIXNUMP (overlay_arrow_string));
25538 row->overlay_arrow_bitmap = XFIXNUM (overlay_arrow_string);
25539 }
25540 overlay_arrow_seen = true;
25541 }
25542
25543
25544 if (!NILP (Vshow_trailing_whitespace))
25545 highlight_trailing_whitespace (it);
25546
25547
25548 compute_line_metrics (it);
25549
25550
25551
25552
25553
25554
25555
25556 row->ends_in_ellipsis_p
25557 = (it->method == GET_FROM_DISPLAY_VECTOR
25558 && it->ellipsis_p);
25559
25560
25561 row->left_user_fringe_bitmap = it->left_user_fringe_bitmap;
25562 row->left_user_fringe_face_id = it->left_user_fringe_face_id;
25563 row->right_user_fringe_bitmap = it->right_user_fringe_bitmap;
25564 row->right_user_fringe_face_id = it->right_user_fringe_face_id;
25565
25566 it->left_user_fringe_bitmap = 0;
25567 it->left_user_fringe_face_id = 0;
25568 it->right_user_fringe_bitmap = 0;
25569 it->right_user_fringe_face_id = 0;
25570
25571
25572
25573
25574
25575
25576 if (MINI_WINDOW_P (it->w) && it->line_wrap == TRUNCATE
25577 && FRAME_WINDOW_P (it->f) && !cursor_in_echo_area)
25578 row->redraw_fringe_bitmaps_p = true;
25579
25580
25581 cvpos = it->w->cursor.vpos;
25582 if ((cvpos < 0
25583
25584
25585
25586
25587
25588
25589
25590
25591 || (it->bidi_p
25592 && !MATRIX_ROW (it->w->desired_matrix, cvpos)->ends_at_zv_p))
25593 && PT >= MATRIX_ROW_START_CHARPOS (row)
25594 && PT <= MATRIX_ROW_END_CHARPOS (row)
25595 && cursor_row_p (row))
25596 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
25597
25598
25599
25600
25601
25602 it->current_x = it->hpos = 0;
25603 it->current_y += row->height;
25604
25605
25606 if (hscroll_this_line)
25607 {
25608 it->first_visible_x = first_visible_x;
25609 it->last_visible_x = last_visible_x;
25610 }
25611 SET_TEXT_POS (it->eol_pos, 0, 0);
25612 ++it->vpos;
25613 ++it->glyph_row;
25614
25615
25616
25617
25618 if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w))
25619 it->glyph_row->reversed_p = row->reversed_p;
25620 it->start = row->end;
25621 return MATRIX_ROW_DISPLAYS_TEXT_P (row);
25622
25623 #undef RECORD_MAX_MIN_POS
25624 }
25625
25626 DEFUN ("current-bidi-paragraph-direction", Fcurrent_bidi_paragraph_direction,
25627 Scurrent_bidi_paragraph_direction, 0, 1, 0,
25628 doc:
25629
25630
25631
25632
25633
25634
25635
25636
25637 )
25638 (Lisp_Object buffer)
25639 {
25640 struct buffer *buf = current_buffer;
25641 struct buffer *old = buf;
25642
25643 if (! NILP (buffer))
25644 {
25645 CHECK_BUFFER (buffer);
25646 buf = XBUFFER (buffer);
25647 }
25648
25649 if (NILP (BVAR (buf, bidi_display_reordering))
25650 || NILP (BVAR (buf, enable_multibyte_characters))
25651
25652
25653 || redisplay__inhibit_bidi)
25654 return Qleft_to_right;
25655 else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
25656 return BVAR (buf, bidi_paragraph_direction);
25657 else
25658 {
25659
25660
25661
25662 struct bidi_it itb;
25663 ptrdiff_t pos = BUF_PT (buf);
25664 ptrdiff_t bytepos = BUF_PT_BYTE (buf);
25665 int c;
25666 void *itb_data = bidi_shelve_cache ();
25667
25668 set_buffer_temp (buf);
25669
25670
25671
25672
25673
25674 if (pos >= ZV && pos > BEGV)
25675 dec_both (&pos, &bytepos);
25676 AUTO_STRING (trailing_white_space, "[\f\t ]*\n");
25677 if (fast_looking_at (trailing_white_space,
25678 pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
25679 {
25680 while ((c = FETCH_BYTE (bytepos)) == '\n'
25681 || c == ' ' || c == '\t' || c == '\f')
25682 {
25683 if (bytepos <= BEGV_BYTE)
25684 break;
25685 bytepos--;
25686 pos--;
25687 }
25688 while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
25689 bytepos--;
25690 }
25691 bidi_init_it (pos, bytepos, FRAME_WINDOW_P (SELECTED_FRAME ()), &itb);
25692 itb.paragraph_dir = NEUTRAL_DIR;
25693 itb.string.s = NULL;
25694 itb.string.lstring = Qnil;
25695 itb.string.bufpos = 0;
25696 itb.string.from_disp_str = false;
25697 itb.string.unibyte = false;
25698
25699
25700
25701 itb.w = NULL;
25702 bidi_paragraph_init (NEUTRAL_DIR, &itb, true);
25703 bidi_unshelve_cache (itb_data, false);
25704 set_buffer_temp (old);
25705 switch (itb.paragraph_dir)
25706 {
25707 case L2R:
25708 return Qleft_to_right;
25709 break;
25710 case R2L:
25711 return Qright_to_left;
25712 break;
25713 default:
25714 emacs_abort ();
25715 }
25716 }
25717 }
25718
25719 DEFUN ("bidi-find-overridden-directionality",
25720 Fbidi_find_overridden_directionality,
25721 Sbidi_find_overridden_directionality, 3, 4, 0,
25722 doc:
25723
25724
25725
25726
25727
25728
25729
25730
25731
25732
25733
25734
25735
25736
25737
25738
25739
25740
25741
25742
25743
25744
25745
25746
25747
25748
25749
25750
25751
25752
25753
25754
25755
25756
25757
25758
25759 )
25760 (Lisp_Object from, Lisp_Object to, Lisp_Object object, Lisp_Object base_dir)
25761 {
25762 struct buffer *buf = current_buffer;
25763 struct buffer *old = buf;
25764 struct window *w = NULL;
25765 bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
25766 struct bidi_it itb;
25767 ptrdiff_t from_pos, to_pos, from_bpos;
25768 void *itb_data;
25769
25770 if (!NILP (object))
25771 {
25772 if (BUFFERP (object))
25773 buf = XBUFFER (object);
25774 else if (WINDOWP (object))
25775 {
25776 w = decode_live_window (object);
25777 buf = XBUFFER (w->contents);
25778 frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
25779 }
25780 else
25781 CHECK_STRING (object);
25782 }
25783
25784 if (STRINGP (object))
25785 {
25786
25787
25788 if (!STRING_MULTIBYTE (object)
25789
25790
25791
25792 || redisplay__inhibit_bidi)
25793 return Qnil;
25794
25795 validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
25796 if (from_pos >= SCHARS (object))
25797 return Qnil;
25798
25799
25800 itb_data = bidi_shelve_cache ();
25801 itb.paragraph_dir = NEUTRAL_DIR;
25802 itb.string.lstring = object;
25803 itb.string.s = NULL;
25804 itb.string.schars = SCHARS (object);
25805 itb.string.bufpos = 0;
25806 itb.string.from_disp_str = false;
25807 itb.string.unibyte = false;
25808 itb.w = w;
25809 bidi_init_it (0, 0, frame_window_p, &itb);
25810 }
25811 else
25812 {
25813
25814
25815 if (NILP (BVAR (buf, bidi_display_reordering))
25816 || NILP (BVAR (buf, enable_multibyte_characters))
25817
25818
25819
25820 || redisplay__inhibit_bidi)
25821 return Qnil;
25822
25823 set_buffer_temp (buf);
25824 validate_region (&from, &to);
25825 from_pos = XFIXNUM (from);
25826 to_pos = XFIXNUM (to);
25827 if (from_pos >= ZV)
25828 return Qnil;
25829
25830
25831 itb_data = bidi_shelve_cache ();
25832 from_bpos = CHAR_TO_BYTE (from_pos);
25833 if (from_pos == BEGV)
25834 {
25835 itb.charpos = BEGV;
25836 itb.bytepos = BEGV_BYTE;
25837 }
25838 else if (FETCH_BYTE (from_bpos - 1) == '\n')
25839 {
25840 itb.charpos = from_pos;
25841 itb.bytepos = from_bpos;
25842 }
25843 else
25844 itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
25845 -1, &itb.bytepos);
25846 itb.paragraph_dir = NEUTRAL_DIR;
25847 itb.string.s = NULL;
25848 itb.string.lstring = Qnil;
25849 itb.string.bufpos = 0;
25850 itb.string.from_disp_str = false;
25851 itb.string.unibyte = false;
25852 itb.w = w;
25853 bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
25854 }
25855
25856 ptrdiff_t found;
25857 bidi_dir_t bdir = EQ (base_dir, Qright_to_left) ? R2L : L2R;
25858 do {
25859 bidi_paragraph_init (bdir, &itb, false);
25860 while ((found = bidi_find_first_overridden (&itb)) < from_pos)
25861 ;
25862 } while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
25863
25864 bidi_unshelve_cache (itb_data, false);
25865 set_buffer_temp (old);
25866
25867 return (from_pos <= found && found < to_pos) ? make_fixnum (found) : Qnil;
25868 }
25869
25870 DEFUN ("move-point-visually", Fmove_point_visually,
25871 Smove_point_visually, 1, 1, 0,
25872 doc:
25873
25874
25875
25876 )
25877 (Lisp_Object direction)
25878 {
25879 struct window *w = XWINDOW (selected_window);
25880 struct buffer *b = XBUFFER (w->contents);
25881 struct glyph_row *row;
25882 int dir;
25883 Lisp_Object paragraph_dir;
25884
25885 #define ROW_GLYPH_NEWLINE_P(ROW,GLYPH) \
25886 (!(ROW)->continued_p \
25887 && NILP ((GLYPH)->object) \
25888 && (GLYPH)->type == CHAR_GLYPH \
25889 && (GLYPH)->u.ch == ' ' \
25890 && (GLYPH)->charpos >= 0 \
25891 && !(GLYPH)->avoid_cursor_p)
25892
25893 CHECK_FIXNUM (direction);
25894 dir = XFIXNUM (direction);
25895 if (dir > 0)
25896 dir = 1;
25897 else
25898 dir = -1;
25899
25900
25901
25902
25903 if (w->window_end_valid
25904 && !windows_or_buffers_changed
25905 && b
25906 && !b->clip_changed
25907 && !b->prevent_redisplay_optimizations_p
25908 && !window_outdated (w)
25909
25910
25911
25912 && w->last_point == BUF_PT (b)
25913 && w->cursor.vpos >= 0
25914 && w->cursor.vpos < w->current_matrix->nrows
25915 && (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
25916 {
25917 struct glyph *g = row->glyphs[TEXT_AREA];
25918 struct glyph *e = dir > 0 ? g + row->used[TEXT_AREA] : g - 1;
25919 struct glyph *gpt = g + w->cursor.hpos;
25920
25921 for (g = gpt + dir; (dir > 0 ? g < e : g > e); g += dir)
25922 {
25923 if (BUFFERP (g->object) && g->charpos != PT)
25924 {
25925 SET_PT (g->charpos);
25926 w->cursor.vpos = -1;
25927 return make_fixnum (PT);
25928 }
25929 else if (!NILP (g->object) && !EQ (g->object, gpt->object))
25930 {
25931 ptrdiff_t new_pos;
25932
25933 if (BUFFERP (gpt->object))
25934 {
25935 new_pos = PT;
25936 if ((gpt->resolved_level - row->reversed_p) % 2 == 0)
25937 new_pos += (row->reversed_p ? -dir : dir);
25938 else
25939 new_pos -= (row->reversed_p ? -dir : dir);
25940 new_pos = clip_to_bounds (BEGV, new_pos, ZV);
25941
25942
25943 if (new_pos == PT)
25944 break;
25945 }
25946 else if (BUFFERP (g->object))
25947 new_pos = g->charpos;
25948 else
25949 break;
25950 SET_PT (new_pos);
25951 w->cursor.vpos = -1;
25952 return make_fixnum (PT);
25953 }
25954 else if (ROW_GLYPH_NEWLINE_P (row, g))
25955 {
25956
25957
25958
25959 if (g->charpos > 0)
25960 SET_PT (g->charpos);
25961 else if (row->ends_at_zv_p && PT != ZV)
25962 SET_PT (ZV);
25963 else if (PT != MATRIX_ROW_END_CHARPOS (row) - 1)
25964 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
25965 else
25966 break;
25967 w->cursor.vpos = -1;
25968 return make_fixnum (PT);
25969 }
25970 }
25971 if (g == e || NILP (g->object))
25972 {
25973 if (row->truncated_on_left_p || row->truncated_on_right_p)
25974 goto simulate_display;
25975 if (!row->reversed_p)
25976 row += dir;
25977 else
25978 row -= dir;
25979 if (!(MATRIX_FIRST_TEXT_ROW (w->current_matrix) <= row
25980 && row < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)))
25981 goto simulate_display;
25982
25983 if (dir > 0)
25984 {
25985 if (row->reversed_p && !row->continued_p)
25986 {
25987 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
25988 w->cursor.vpos = -1;
25989 return make_fixnum (PT);
25990 }
25991 g = row->glyphs[TEXT_AREA];
25992 e = g + row->used[TEXT_AREA];
25993 for ( ; g < e; g++)
25994 {
25995 if (BUFFERP (g->object)
25996
25997
25998
25999 || ROW_GLYPH_NEWLINE_P (row, g)
26000
26001
26002 || (row->ends_at_zv_p
26003 && !row->reversed_p
26004 && NILP (g->object)
26005 && g->type == CHAR_GLYPH
26006 && g->u.ch == ' '))
26007 {
26008 if (g->charpos > 0)
26009 SET_PT (g->charpos);
26010 else if (!row->reversed_p
26011 && row->ends_at_zv_p
26012 && PT != ZV)
26013 SET_PT (ZV);
26014 else
26015 continue;
26016 w->cursor.vpos = -1;
26017 return make_fixnum (PT);
26018 }
26019 }
26020 }
26021 else
26022 {
26023 if (!row->reversed_p && !row->continued_p)
26024 {
26025 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26026 w->cursor.vpos = -1;
26027 return make_fixnum (PT);
26028 }
26029 e = row->glyphs[TEXT_AREA];
26030 g = e + row->used[TEXT_AREA] - 1;
26031 for ( ; g >= e; g--)
26032 {
26033 if (BUFFERP (g->object)
26034 || (ROW_GLYPH_NEWLINE_P (row, g)
26035 && g->charpos > 0)
26036
26037
26038
26039 || g->type == STRETCH_GLYPH
26040 || (row->ends_at_zv_p
26041 && row->reversed_p
26042 && NILP (g->object)
26043 && g->type == CHAR_GLYPH
26044 && g->u.ch == ' '))
26045 {
26046 if (g->charpos > 0)
26047 SET_PT (g->charpos);
26048 else if (row->reversed_p
26049 && row->ends_at_zv_p
26050 && PT != ZV)
26051 SET_PT (ZV);
26052 else
26053 continue;
26054 w->cursor.vpos = -1;
26055 return make_fixnum (PT);
26056 }
26057 }
26058 }
26059 }
26060 }
26061
26062 simulate_display:
26063
26064
26065
26066
26067 if (b)
26068 paragraph_dir = Fcurrent_bidi_paragraph_direction (w->contents);
26069 else
26070 paragraph_dir = Qleft_to_right;
26071 if (EQ (paragraph_dir, Qright_to_left))
26072 dir = -dir;
26073 if (PT <= BEGV && dir < 0)
26074 xsignal0 (Qbeginning_of_buffer);
26075 else if (PT >= ZV && dir > 0)
26076 xsignal0 (Qend_of_buffer);
26077 else
26078 {
26079 struct text_pos pt;
26080 struct it it;
26081 int pt_x, target_x, pixel_width, pt_vpos;
26082 bool at_eol_p;
26083 bool overshoot_expected = false;
26084 bool target_is_eol_p = false;
26085 void *itdata = bidi_shelve_cache ();
26086
26087
26088 SET_TEXT_POS (pt, PT, PT_BYTE);
26089 start_display (&it, w, pt);
26090
26091
26092
26093
26094
26095
26096 if (it.line_wrap == TRUNCATE)
26097 it.last_visible_x = DISP_INFINITY;
26098
26099 if (it.cmp_it.id < 0
26100 && it.method == GET_FROM_STRING
26101 && it.area == TEXT_AREA
26102 && it.string_from_display_prop_p
26103 && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER))
26104 overshoot_expected = true;
26105
26106
26107
26108
26109
26110 reseat:
26111 reseat_at_previous_visible_line_start (&it);
26112 it.current_x = it.hpos = it.current_y = it.vpos = 0;
26113 if (IT_CHARPOS (it) != PT)
26114 {
26115 move_it_to (&it, overshoot_expected ? PT - 1 : PT,
26116 -1, -1, -1, MOVE_TO_POS);
26117
26118
26119
26120 if (it.method == GET_FROM_DISPLAY_VECTOR
26121 && it.current.dpvec_index > 0
26122 && !overshoot_expected)
26123 {
26124 overshoot_expected = true;
26125 goto reseat;
26126 }
26127 else if (IT_CHARPOS (it) != PT && !overshoot_expected)
26128 move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
26129 }
26130 pt_x = it.current_x;
26131 pt_vpos = it.vpos;
26132 if (dir > 0 || overshoot_expected)
26133 {
26134 struct glyph_row *row = it.glyph_row;
26135
26136
26137
26138
26139 if (pt_x == 0)
26140 get_next_display_element (&it);
26141 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26142 it.glyph_row = NULL;
26143 PRODUCE_GLYPHS (&it);
26144 it.glyph_row = row;
26145
26146
26147
26148 it.current_x = pt_x;
26149 }
26150 else
26151 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26152 pixel_width = it.pixel_width;
26153 if (overshoot_expected && at_eol_p)
26154 pixel_width = 0;
26155 else if (pixel_width <= 0)
26156 pixel_width = 1;
26157
26158
26159
26160
26161 if (overshoot_expected)
26162 {
26163 if (it.bidi_p)
26164 pt_x += pixel_width * it.bidi_it.scan_dir;
26165 else
26166 pt_x += pixel_width;
26167 }
26168
26169
26170
26171
26172
26173
26174
26175 if (dir > 0)
26176 target_x = pt_x + pixel_width;
26177 else
26178 target_x = pt_x - (!FRAME_WINDOW_P (it.f)) * pixel_width;
26179
26180
26181
26182
26183
26184 if (dir < 0)
26185 {
26186 if (pt_x > 0)
26187 {
26188 start_display (&it, w, pt);
26189 if (it.line_wrap == TRUNCATE)
26190 it.last_visible_x = DISP_INFINITY;
26191 reseat_at_previous_visible_line_start (&it);
26192 it.current_x = it.current_y = it.hpos = 0;
26193 if (pt_vpos != 0)
26194 move_it_by_lines (&it, pt_vpos);
26195 }
26196 else
26197 {
26198 move_it_by_lines (&it, -1);
26199 target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f);
26200 target_is_eol_p = true;
26201
26202
26203
26204
26205
26206
26207
26208
26209
26210
26211 if (!FRAME_WINDOW_P (it.f) && it.line_wrap == WORD_WRAP)
26212 {
26213 void *it_data = NULL;
26214 struct it it2;
26215
26216 SAVE_IT (it2, it, it_data);
26217 move_it_in_display_line_to (&it, ZV, target_x,
26218 MOVE_TO_POS | MOVE_TO_X);
26219
26220
26221 if (it.current_x != target_x)
26222 target_x = it.current_x - 1;
26223 RESTORE_IT (&it, &it2, it_data);
26224 }
26225 }
26226 }
26227 else
26228 {
26229 if (at_eol_p
26230 || (target_x >= it.last_visible_x
26231 && it.line_wrap != TRUNCATE))
26232 {
26233 if (pt_x > 0)
26234 move_it_by_lines (&it, 0);
26235 move_it_by_lines (&it, 1);
26236 target_x = 0;
26237 }
26238 }
26239
26240
26241
26242
26243
26244
26245
26246 if (FRAME_WINDOW_P (it.f) && dir < 0)
26247 {
26248 struct text_pos new_pos;
26249 enum move_it_result rc = MOVE_X_REACHED;
26250
26251 if (it.current_x == 0)
26252 get_next_display_element (&it);
26253 if (it.what == IT_COMPOSITION)
26254 {
26255 new_pos.charpos = it.cmp_it.charpos;
26256 new_pos.bytepos = -1;
26257 }
26258 else
26259 new_pos = it.current.pos;
26260
26261 while (it.current_x + it.pixel_width <= target_x
26262 && (rc == MOVE_X_REACHED
26263
26264
26265
26266 || (it.line_wrap == WORD_WRAP
26267 && rc == MOVE_POS_MATCH_OR_ZV)))
26268 {
26269 int new_x = it.current_x + it.pixel_width;
26270
26271
26272
26273
26274
26275
26276
26277 if (it.what == IT_COMPOSITION)
26278 {
26279 new_pos.charpos = it.cmp_it.charpos;
26280 new_pos.bytepos = -1;
26281 }
26282 else
26283 new_pos = it.current.pos;
26284 if (new_x == it.current_x)
26285 new_x++;
26286 rc = move_it_in_display_line_to (&it, ZV, new_x,
26287 MOVE_TO_POS | MOVE_TO_X);
26288 if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p)
26289 break;
26290 }
26291
26292
26293 if (new_pos.bytepos == -1)
26294 new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
26295 it.current.pos = new_pos;
26296 }
26297 else if (it.current_x != target_x)
26298 move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X);
26299
26300
26301
26302 if (dir > 0)
26303 {
26304 while (IT_CHARPOS (it) == PT)
26305 {
26306 set_iterator_to_next (&it, false);
26307 if (!get_next_display_element (&it))
26308 break;
26309 }
26310 }
26311
26312
26313 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
26314 bidi_unshelve_cache (itdata, false);
26315 }
26316
26317 return make_fixnum (PT);
26318
26319 #undef ROW_GLYPH_NEWLINE_P
26320 }
26321
26322 DEFUN ("bidi-resolved-levels", Fbidi_resolved_levels,
26323 Sbidi_resolved_levels, 0, 1, 0,
26324 doc:
26325
26326
26327
26328
26329
26330
26331
26332
26333
26334
26335
26336
26337
26338
26339
26340
26341
26342
26343
26344
26345
26346
26347
26348
26349
26350 )
26351 (Lisp_Object vpos)
26352 {
26353 struct window *w = XWINDOW (selected_window);
26354 struct buffer *b = XBUFFER (w->contents);
26355 int nrow;
26356 struct glyph_row *row;
26357
26358 if (NILP (vpos))
26359 {
26360 int d1, d2, d3, d4, d5;
26361
26362 pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow);
26363 }
26364 else
26365 {
26366 CHECK_FIXNUM (vpos);
26367 nrow = XFIXNUM (vpos);
26368 }
26369
26370
26371 if (w->window_end_valid
26372 && !windows_or_buffers_changed
26373 && b
26374 && !b->clip_changed
26375 && !b->prevent_redisplay_optimizations_p
26376 && !window_outdated (w)
26377 && nrow >= 0
26378 && nrow < w->current_matrix->nrows
26379 && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p
26380 && MATRIX_ROW_DISPLAYS_TEXT_P (row))
26381 {
26382 struct glyph *g, *e, *g1;
26383 int nglyphs, i;
26384 Lisp_Object levels;
26385
26386 if (!row->reversed_p)
26387 {
26388 g = g1 = row->glyphs[TEXT_AREA];
26389 e = g + row->used[TEXT_AREA];
26390
26391
26392
26393 while (g < e
26394 && NILP (g->object)
26395 && g->charpos < 0)
26396 g++;
26397 g1 = g;
26398
26399
26400 for (nglyphs = 0; g < e && !NILP (g->object); g++)
26401 nglyphs++;
26402
26403
26404 levels = make_uninit_vector (nglyphs);
26405 for (i = 0; g1 < g; i++, g1++)
26406 ASET (levels, i, make_fixnum (g1->resolved_level));
26407 }
26408 else
26409 {
26410 g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
26411 e = row->glyphs[TEXT_AREA] - 1;
26412 while (g > e
26413 && NILP (g->object)
26414 && g->charpos < 0)
26415 g--;
26416 g1 = g;
26417 for (nglyphs = 0; g > e && !NILP (g->object); g--)
26418 nglyphs++;
26419 levels = make_uninit_vector (nglyphs);
26420 for (i = 0; g1 > g; i++, g1--)
26421 ASET (levels, i, make_fixnum (g1->resolved_level));
26422 }
26423 return levels;
26424 }
26425 else
26426 return Qnil;
26427 }
26428
26429
26430
26431
26432
26433
26434
26435
26436
26437
26438
26439
26440
26441
26442
26443
26444
26445 static void
26446 display_menu_bar (struct window *w)
26447 {
26448 struct frame *f = XFRAME (WINDOW_FRAME (w));
26449 struct it it;
26450 Lisp_Object items;
26451 int i;
26452
26453
26454 #ifdef HAVE_NTGUI
26455 if (FRAME_W32_P (f))
26456 return;
26457 #endif
26458 #if defined (HAVE_PGTK)
26459 if (FRAME_PGTK_P (f))
26460 return;
26461 #endif
26462
26463 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26464 if (FRAME_X_P (f))
26465 return;
26466 #endif
26467
26468 #ifdef HAVE_NS
26469 if (FRAME_NS_P (f))
26470 return;
26471 #endif
26472
26473 #ifdef HAVE_HAIKU
26474 if (FRAME_HAIKU_P (f))
26475 return;
26476 #endif
26477
26478 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26479 eassert (!FRAME_WINDOW_P (f));
26480 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
26481 it.first_visible_x = 0;
26482 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26483 #elif defined (HAVE_X_WINDOWS)
26484 if (FRAME_WINDOW_P (f))
26485 {
26486
26487
26488 struct window *menu_w;
26489 menu_w = XWINDOW (f->menu_bar_window);
26490 init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
26491 MENU_FACE_ID);
26492 it.first_visible_x = 0;
26493 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26494 }
26495 else
26496 #endif
26497 {
26498
26499
26500 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
26501 MENU_FACE_ID);
26502 it.first_visible_x = 0;
26503 it.last_visible_x = FRAME_COLS (f);
26504 }
26505
26506
26507
26508
26509 it.paragraph_embedding = L2R;
26510
26511
26512 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
26513 {
26514 struct glyph_row *row = it.glyph_row + i;
26515 clear_glyph_row (row);
26516 row->enabled_p = true;
26517 row->full_width_p = true;
26518 row->reversed_p = false;
26519 }
26520
26521
26522 items = FRAME_MENU_BAR_ITEMS (it.f);
26523 for (i = 0; i < ASIZE (items); i += 4)
26524 {
26525 Lisp_Object string;
26526
26527
26528 string = AREF (items, i + 1);
26529 if (NILP (string))
26530 break;
26531
26532
26533 ASET (items, i + 3, make_fixnum (it.hpos));
26534
26535
26536 if (it.current_x < it.last_visible_x)
26537 display_string (NULL, string, Qnil, 0, 0, &it,
26538 SCHARS (string) + 1, 0, 0, STRING_MULTIBYTE (string));
26539 }
26540
26541
26542 if (it.current_x < it.last_visible_x)
26543 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
26544
26545
26546 compute_line_metrics (&it);
26547 }
26548
26549
26550 static void
26551 deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
26552 {
26553 struct glyph *pointers[1 + LAST_AREA];
26554 int to_used = to->used[TEXT_AREA];
26555
26556
26557 memcpy (pointers, to->glyphs, sizeof to->glyphs);
26558
26559
26560 *to = *from;
26561
26562
26563 memcpy (to->glyphs, pointers, sizeof to->glyphs);
26564
26565
26566 memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA],
26567 min (from->used[TEXT_AREA], to_used) * sizeof (struct glyph));
26568
26569
26570
26571 if (to_used > from->used[TEXT_AREA])
26572 fill_up_frame_row_with_spaces (to, to_used);
26573 }
26574
26575
26576
26577
26578
26579
26580
26581
26582
26583
26584
26585
26586
26587
26588
26589
26590
26591
26592
26593
26594
26595
26596 void
26597 display_tty_menu_item (const char *item_text, int width, int face_id,
26598 int x, int y, bool submenu)
26599 {
26600 struct it it;
26601 struct frame *f = SELECTED_FRAME ();
26602 struct window *w = XWINDOW (f->selected_window);
26603 struct glyph_row *row;
26604 size_t item_len = strlen (item_text);
26605
26606 eassert (FRAME_TERMCAP_P (f));
26607
26608
26609
26610
26611
26612
26613 if (y >= f->desired_matrix->nrows)
26614 return;
26615
26616 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
26617 it.first_visible_x = 0;
26618 it.last_visible_x = FRAME_COLS (f) - 1;
26619 row = it.glyph_row;
26620
26621 deep_copy_glyph_row (row, f->current_matrix->rows + y);
26622 bool saved_width = row->full_width_p;
26623 row->full_width_p = true;
26624 bool saved_reversed = row->reversed_p;
26625 row->reversed_p = false;
26626 row->enabled_p = true;
26627
26628
26629
26630 eassert (x < f->desired_matrix->matrix_w);
26631 it.current_x = it.hpos = x;
26632 it.current_y = it.vpos = y;
26633 int saved_used = row->used[TEXT_AREA];
26634 bool saved_truncated = row->truncated_on_right_p;
26635 row->used[TEXT_AREA] = x;
26636 it.face_id = face_id;
26637 it.line_wrap = TRUNCATE;
26638
26639
26640
26641
26642
26643
26644 it.paragraph_embedding = L2R;
26645
26646
26647 display_string (" ", Qnil, Qnil, 0, 0, &it, 1, 0, FRAME_COLS (f) - 1, -1);
26648 width--;
26649
26650 if (submenu)
26651 {
26652 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26653 item_len, 0, FRAME_COLS (f) - 1, -1);
26654 width -= item_len;
26655
26656 display_string (" >", Qnil, Qnil, 0, 0, &it, width, 0,
26657 FRAME_COLS (f) - 1, -1);
26658 }
26659 else
26660 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26661 width, 0, FRAME_COLS (f) - 1, -1);
26662
26663 row->used[TEXT_AREA] = max (saved_used, row->used[TEXT_AREA]);
26664 row->truncated_on_right_p = saved_truncated;
26665 row->hash = row_hash (row);
26666 row->full_width_p = saved_width;
26667 row->reversed_p = saved_reversed;
26668 }
26669
26670
26671
26672
26673
26674
26675
26676
26677
26678
26679 static int
26680 redisplay_mode_lines (Lisp_Object window, bool force)
26681 {
26682 int nwindows = 0;
26683
26684 while (!NILP (window))
26685 {
26686 struct window *w = XWINDOW (window);
26687
26688 if (WINDOWP (w->contents))
26689 nwindows += redisplay_mode_lines (w->contents, force);
26690 else if (force
26691 || FRAME_GARBAGED_P (XFRAME (w->frame))
26692 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
26693 {
26694 struct text_pos lpoint;
26695 struct buffer *old = current_buffer;
26696
26697
26698 SET_TEXT_POS (lpoint, PT, PT_BYTE);
26699 set_buffer_internal_1 (XBUFFER (w->contents));
26700
26701
26702
26703 if (!EQ (window, selected_window))
26704 {
26705 struct text_pos pt;
26706
26707 CLIP_TEXT_POS_FROM_MARKER (pt, w->pointm);
26708 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
26709 }
26710
26711
26712 clear_glyph_matrix (w->desired_matrix);
26713 if (display_mode_lines (w))
26714 ++nwindows;
26715
26716
26717 set_buffer_internal_1 (old);
26718 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
26719 }
26720
26721 window = w->next;
26722 }
26723
26724 return nwindows;
26725 }
26726
26727
26728
26729
26730
26731
26732 static int
26733 display_mode_lines (struct window *w)
26734 {
26735 Lisp_Object old_selected_window = selected_window;
26736 Lisp_Object new_frame = w->frame;
26737 specpdl_ref count = SPECPDL_INDEX ();
26738 int n = 0;
26739
26740 record_unwind_protect (restore_selected_window, selected_window);
26741 record_unwind_protect
26742 (restore_frame_selected_window, XFRAME (new_frame)->selected_window);
26743
26744 if (window_wants_mode_line (w))
26745 {
26746 Lisp_Object window;
26747 Lisp_Object default_help
26748 = buffer_local_value (Qmode_line_default_help_echo, w->contents);
26749
26750
26751
26752 XSETWINDOW (window, w);
26753 if (FUNCTIONP (default_help))
26754 wset_mode_line_help_echo (w, safe_call1 (default_help, window));
26755 else if (STRINGP (default_help))
26756 wset_mode_line_help_echo (w, default_help);
26757 else
26758 wset_mode_line_help_echo (w, Qnil);
26759 }
26760
26761 selected_frame = new_frame;
26762
26763
26764 XSETWINDOW (selected_window, w);
26765 XFRAME (new_frame)->selected_window = selected_window;
26766
26767
26768 line_number_displayed = false;
26769 w->column_number_displayed = -1;
26770
26771 if (window_wants_mode_line (w))
26772 {
26773 Lisp_Object window_mode_line_format
26774 = window_parameter (w, Qmode_line_format);
26775 struct window *sel_w = XWINDOW (old_selected_window);
26776
26777
26778 display_mode_line (w,
26779 CURRENT_MODE_LINE_ACTIVE_FACE_ID_3 (sel_w, sel_w, w),
26780 NILP (window_mode_line_format)
26781 ? BVAR (current_buffer, mode_line_format)
26782 : window_mode_line_format);
26783 ++n;
26784 }
26785
26786 if (window_wants_tab_line (w))
26787 {
26788 Lisp_Object window_tab_line_format
26789 = window_parameter (w, Qtab_line_format);
26790
26791 display_mode_line (w, TAB_LINE_FACE_ID,
26792 NILP (window_tab_line_format)
26793 ? BVAR (current_buffer, tab_line_format)
26794 : window_tab_line_format);
26795 ++n;
26796 }
26797
26798 if (window_wants_header_line (w))
26799 {
26800 Lisp_Object window_header_line_format
26801 = window_parameter (w, Qheader_line_format);
26802
26803 display_mode_line (w, HEADER_LINE_FACE_ID,
26804 NILP (window_header_line_format)
26805 ? BVAR (current_buffer, header_line_format)
26806 : window_header_line_format);
26807 ++n;
26808 }
26809
26810 unbind_to (count, Qnil);
26811
26812 if (n > 0)
26813 w->must_be_updated_p = true;
26814 return n;
26815 }
26816
26817
26818
26819
26820
26821
26822
26823
26824 static int
26825 display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
26826 {
26827 struct it it;
26828 struct face *face;
26829 specpdl_ref count = SPECPDL_INDEX ();
26830
26831 init_iterator (&it, w, -1, -1, NULL, face_id);
26832
26833
26834 it.glyph_row->enabled_p = false;
26835 prepare_desired_row (w, it.glyph_row, true);
26836
26837 it.glyph_row->mode_line_p = true;
26838 if (face_id == TAB_LINE_FACE_ID)
26839 {
26840 it.glyph_row->tab_line_p = true;
26841 w->desired_matrix->tab_line_p = true;
26842 }
26843 else if (face_id == HEADER_LINE_FACE_ID)
26844 w->desired_matrix->header_line_p = true;
26845
26846
26847
26848
26849 it.paragraph_embedding = L2R;
26850
26851 record_unwind_protect (unwind_format_mode_line,
26852 format_mode_line_unwind_data (NULL, NULL,
26853 Qnil, false));
26854
26855
26856
26857
26858 push_kboard (FRAME_KBOARD (it.f));
26859 record_unwind_save_match_data ();
26860
26861 if (NILP (Vmode_line_compact)
26862 || face_id == HEADER_LINE_FACE_ID || face_id == TAB_LINE_FACE_ID)
26863 {
26864 mode_line_target = MODE_LINE_DISPLAY;
26865 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
26866 }
26867 else
26868 {
26869 Lisp_Object mode_string = Fformat_mode_line (format, Qnil, Qnil, Qnil);
26870 if (EQ (Vmode_line_compact, Qlong)
26871 && WINDOW_TOTAL_COLS (w) >= SCHARS (mode_string))
26872 {
26873
26874
26875 display_string (NULL, mode_string, Qnil,
26876 0, 0, &it, 0, 0, 0,
26877 STRING_MULTIBYTE (mode_string));
26878 }
26879 else
26880 {
26881
26882 ptrdiff_t i = 0, i_byte = 0, start = 0;
26883 int prev = 0;
26884
26885 while (i < SCHARS (mode_string))
26886 {
26887 int c = fetch_string_char_advance (mode_string, &i, &i_byte);
26888 if (c == ' ' && prev == ' ')
26889 {
26890 display_string (NULL,
26891 Fsubstring (mode_string, make_fixnum (start),
26892 make_fixnum (i - 1)),
26893 Qnil, 0, 0, &it, 0, 0, 0,
26894 STRING_MULTIBYTE (mode_string));
26895
26896 while (c == ' ' && i < SCHARS (mode_string))
26897 c = fetch_string_char_advance (mode_string, &i, &i_byte);
26898 start = i - 1;
26899 }
26900 prev = c;
26901 }
26902
26903
26904 if (start < i)
26905 display_string (NULL,
26906 Fsubstring (mode_string, make_fixnum (start),
26907 make_fixnum (i)),
26908 Qnil, 0, 0, &it, 0, 0, 0,
26909 STRING_MULTIBYTE (mode_string));
26910 }
26911 }
26912 pop_kboard ();
26913
26914 unbind_to (count, Qnil);
26915
26916
26917 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
26918
26919 compute_line_metrics (&it);
26920 it.glyph_row->full_width_p = true;
26921 it.glyph_row->continued_p = false;
26922 it.glyph_row->truncated_on_left_p = false;
26923 it.glyph_row->truncated_on_right_p = false;
26924
26925
26926 face = FACE_FROM_ID (it.f, face_id);
26927 extend_face_to_end_of_line (&it);
26928 if (face->box != FACE_NO_BOX)
26929 {
26930 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
26931 + it.glyph_row->used[TEXT_AREA] - 1);
26932 int box_thickness = face->box_vertical_line_width;
26933 last->right_box_line_p = true;
26934
26935
26936
26937
26938
26939
26940 if (box_thickness > 0)
26941 last->pixel_width += max (0, (box_thickness
26942 - (it.current_x - it.last_visible_x)));
26943 }
26944
26945 return it.glyph_row->height;
26946 }
26947
26948
26949
26950
26951 static Lisp_Object
26952 move_elt_to_front (Lisp_Object elt, Lisp_Object list)
26953 {
26954 register Lisp_Object tail, prev;
26955 register Lisp_Object tem;
26956
26957 tail = list;
26958 prev = Qnil;
26959 while (CONSP (tail))
26960 {
26961 tem = XCAR (tail);
26962
26963 if (EQ (elt, tem))
26964 {
26965
26966 if (NILP (prev))
26967 list = XCDR (tail);
26968 else
26969 Fsetcdr (prev, XCDR (tail));
26970
26971
26972 Fsetcdr (tail, list);
26973 return tail;
26974 }
26975 else
26976 prev = tail;
26977 tail = XCDR (tail);
26978 maybe_quit ();
26979 }
26980
26981
26982 return list;
26983 }
26984
26985
26986
26987
26988
26989 static Lisp_Object
26990 safe_set_text_properties (ptrdiff_t nargs, Lisp_Object *args)
26991 {
26992 eassert (nargs == 4);
26993 return Fset_text_properties (args[0], args[1], args[2], args[3]);
26994 }
26995
26996
26997
26998
26999
27000
27001
27002
27003
27004
27005
27006
27007
27008
27009
27010
27011
27012
27013
27014
27015
27016
27017
27018
27019
27020 static int
27021 display_mode_element (struct it *it, int depth, int field_width, int precision,
27022 Lisp_Object elt, Lisp_Object props, bool risky)
27023 {
27024 int n = 0, field, prec;
27025 bool literal = false;
27026
27027 tail_recurse:
27028 if (depth > 100)
27029 elt = build_string ("*too-deep*");
27030
27031 depth++;
27032
27033 switch (XTYPE (elt))
27034 {
27035 case Lisp_String:
27036 {
27037
27038 unsigned char c;
27039 ptrdiff_t offset = 0;
27040
27041 if (SCHARS (elt) > 0
27042 && (!NILP (props) || risky))
27043 {
27044 Lisp_Object oprops, aelt;
27045 oprops = Ftext_properties_at (make_fixnum (0), elt);
27046
27047
27048
27049
27050
27051 if (NILP (Fequal (props, oprops)) || risky)
27052 {
27053
27054
27055 if (! NILP (oprops) && !risky)
27056 {
27057 Lisp_Object tem;
27058
27059 oprops = Fcopy_sequence (oprops);
27060 tem = props;
27061 while (CONSP (tem))
27062 {
27063 oprops = plist_put (oprops, XCAR (tem),
27064 XCAR (XCDR (tem)));
27065 tem = XCDR (XCDR (tem));
27066 }
27067 props = oprops;
27068 }
27069
27070 aelt = Fassoc (elt, mode_line_proptrans_alist, Qnil);
27071 if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
27072 {
27073
27074
27075 elt = XCAR (aelt);
27076 mode_line_proptrans_alist
27077 = move_elt_to_front (aelt, mode_line_proptrans_alist);
27078 }
27079 else
27080 {
27081 Lisp_Object tem;
27082
27083
27084
27085 if (! NILP (aelt))
27086 mode_line_proptrans_alist
27087 = Fdelq (aelt, mode_line_proptrans_alist);
27088
27089 elt = Fcopy_sequence (elt);
27090
27091
27092
27093 internal_condition_case_n (safe_set_text_properties,
27094 4,
27095 ((Lisp_Object [])
27096 {make_fixnum (0),
27097 Flength (elt),
27098 props,
27099 elt}),
27100 Qt, safe_eval_handler);
27101
27102 mode_line_proptrans_alist
27103 = Fcons (Fcons (elt, props),
27104 mode_line_proptrans_alist);
27105
27106
27107 tem = Fnthcdr (make_fixnum (50),
27108 mode_line_proptrans_alist);
27109 if (! NILP (tem))
27110 XSETCDR (tem, Qnil);
27111 }
27112 }
27113 }
27114
27115 offset = 0;
27116
27117 if (literal)
27118 {
27119 prec = precision - n;
27120 switch (mode_line_target)
27121 {
27122 case MODE_LINE_NOPROP:
27123 case MODE_LINE_TITLE:
27124 n += store_mode_line_noprop (SSDATA (elt), -1, prec);
27125 break;
27126 case MODE_LINE_STRING:
27127 n += store_mode_line_string (NULL, elt, true, 0, prec, Qnil);
27128 break;
27129 case MODE_LINE_DISPLAY:
27130 n += display_string (NULL, elt, Qnil, 0, 0, it,
27131 0, prec, 0, STRING_MULTIBYTE (elt));
27132 break;
27133 }
27134
27135 break;
27136 }
27137
27138
27139
27140 while ((precision <= 0 || n < precision)
27141 && SREF (elt, offset) != 0
27142 && (mode_line_target != MODE_LINE_DISPLAY
27143 || it->current_x < it->last_visible_x))
27144 {
27145 ptrdiff_t last_offset = offset;
27146
27147
27148 while ((c = SREF (elt, offset++)) != '\0' && c != '%')
27149 ;
27150
27151 if (offset - 1 != last_offset)
27152 {
27153 ptrdiff_t nchars, nbytes;
27154
27155
27156
27157
27158 offset--;
27159
27160 prec = c_string_width (SDATA (elt) + last_offset,
27161 offset - last_offset, precision - n,
27162 &nchars, &nbytes);
27163
27164 switch (mode_line_target)
27165 {
27166 case MODE_LINE_NOPROP:
27167 case MODE_LINE_TITLE:
27168 n += store_mode_line_noprop (SSDATA (elt) + last_offset, 0, prec);
27169 break;
27170 case MODE_LINE_STRING:
27171 {
27172 ptrdiff_t bytepos = last_offset;
27173 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27174 ptrdiff_t endpos = (precision <= 0
27175 ? string_byte_to_char (elt, offset)
27176 : charpos + nchars);
27177 Lisp_Object mode_string
27178 = Fsubstring (elt, make_fixnum (charpos),
27179 make_fixnum (endpos));
27180 n += store_mode_line_string (NULL, mode_string, false,
27181 0, 0, Qnil);
27182 }
27183 break;
27184 case MODE_LINE_DISPLAY:
27185 {
27186 ptrdiff_t bytepos = last_offset;
27187 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27188
27189 if (precision <= 0)
27190 nchars = string_byte_to_char (elt, offset) - charpos;
27191 n += display_string (NULL, elt, Qnil, 0, charpos,
27192 it, 0, nchars, 0,
27193 STRING_MULTIBYTE (elt));
27194 }
27195 break;
27196 }
27197 }
27198 else
27199 {
27200 ptrdiff_t percent_position = offset;
27201
27202
27203
27204 field = 0;
27205 while ((c = SREF (elt, offset++)) >= '0' && c <= '9')
27206 field = field * 10 + c - '0';
27207
27208
27209 if (field_width - n > 0 && field > field_width - n)
27210 field = field_width - n;
27211
27212
27213 prec = precision - n;
27214
27215 if (c == 'M')
27216 n += display_mode_element (it, depth, field, prec,
27217 Vglobal_mode_string, props,
27218 risky);
27219 else if (c != 0)
27220 {
27221 bool multibyte;
27222 ptrdiff_t bytepos, charpos;
27223 const char *spec;
27224 Lisp_Object string;
27225
27226 bytepos = percent_position;
27227 charpos = (STRING_MULTIBYTE (elt)
27228 ? string_byte_to_char (elt, bytepos)
27229 : bytepos);
27230 spec = decode_mode_spec (it->w, c, field, &string);
27231 eassert (NILP (string) || STRINGP (string));
27232 multibyte = !NILP (string) && STRING_MULTIBYTE (string);
27233
27234
27235 ptrdiff_t nbytes = strlen (spec);
27236 ptrdiff_t nchars, mb_nbytes;
27237 parse_str_as_multibyte ((const unsigned char *)spec, nbytes,
27238 &nchars, &mb_nbytes);
27239 if (!(nbytes == nchars || nbytes != mb_nbytes))
27240 multibyte = true;
27241
27242 switch (mode_line_target)
27243 {
27244 case MODE_LINE_NOPROP:
27245 case MODE_LINE_TITLE:
27246 n += store_mode_line_noprop (spec, field, prec);
27247 break;
27248 case MODE_LINE_STRING:
27249 {
27250 Lisp_Object tem = build_string (spec);
27251 props = Ftext_properties_at (make_fixnum (charpos), elt);
27252
27253 n += store_mode_line_string (NULL, tem, false,
27254 field, prec, props);
27255 }
27256 break;
27257 case MODE_LINE_DISPLAY:
27258 {
27259 int nglyphs_before, nwritten;
27260
27261 nglyphs_before = it->glyph_row->used[TEXT_AREA];
27262 nwritten = display_string (spec, string, elt,
27263 charpos, 0, it,
27264 field, prec, 0,
27265 multibyte);
27266
27267
27268
27269
27270 if (nwritten > 0)
27271 {
27272 struct glyph *glyph
27273 = (it->glyph_row->glyphs[TEXT_AREA]
27274 + nglyphs_before);
27275 int i;
27276
27277 for (i = 0; i < nwritten; ++i)
27278 {
27279 glyph[i].object = elt;
27280 glyph[i].charpos = charpos;
27281 }
27282
27283 n += nwritten;
27284 }
27285 }
27286 break;
27287 }
27288 }
27289 else
27290 break;
27291 }
27292 }
27293 }
27294 break;
27295
27296 case Lisp_Symbol:
27297
27298
27299
27300
27301 {
27302 register Lisp_Object tem;
27303
27304
27305
27306 if (NILP (Fget (elt, Qrisky_local_variable)))
27307 risky = true;
27308
27309 tem = Fboundp (elt);
27310 if (!NILP (tem))
27311 {
27312 tem = Fsymbol_value (elt);
27313
27314
27315 if (STRINGP (tem))
27316 literal = true;
27317
27318 if (!EQ (tem, elt))
27319 {
27320
27321 elt = tem;
27322 goto tail_recurse;
27323 }
27324 }
27325 }
27326 break;
27327
27328 case Lisp_Cons:
27329 {
27330 register Lisp_Object car, tem;
27331
27332
27333
27334
27335
27336
27337
27338
27339
27340
27341 car = XCAR (elt);
27342 if (EQ (car, QCeval))
27343 {
27344
27345
27346
27347 if (risky)
27348 break;
27349
27350 if (CONSP (XCDR (elt)))
27351 {
27352 Lisp_Object spec;
27353 spec = safe__eval (true, XCAR (XCDR (elt)));
27354
27355
27356
27357
27358
27359
27360 if (!FRAME_LIVE_P (it->f))
27361 signal_error (":eval deleted the frame being displayed", elt);
27362 n += display_mode_element (it, depth, field_width - n,
27363 precision - n, spec, props,
27364 risky);
27365 }
27366 }
27367 else if (EQ (car, QCpropertize))
27368 {
27369
27370
27371
27372 if (risky)
27373 break;
27374
27375 if (CONSP (XCDR (elt)))
27376 n += display_mode_element (it, depth, field_width - n,
27377 precision - n, XCAR (XCDR (elt)),
27378 XCDR (XCDR (elt)), risky);
27379 }
27380 else if (SYMBOLP (car))
27381 {
27382 tem = Fboundp (car);
27383 elt = XCDR (elt);
27384 if (!CONSP (elt))
27385 goto invalid;
27386
27387
27388 if (!NILP (tem))
27389 {
27390 tem = Fsymbol_value (car);
27391 if (!NILP (tem))
27392 {
27393 elt = XCAR (elt);
27394 goto tail_recurse;
27395 }
27396 }
27397
27398
27399
27400 elt = XCDR (elt);
27401 if (NILP (elt))
27402 break;
27403 else if (!CONSP (elt))
27404 goto invalid;
27405 elt = XCAR (elt);
27406 goto tail_recurse;
27407 }
27408 else if (FIXNUMP (car))
27409 {
27410 register int lim = XFIXNUM (car);
27411 elt = XCDR (elt);
27412 if (lim < 0)
27413 {
27414
27415 if (precision <= 0)
27416 precision = -lim;
27417 else
27418 precision = min (precision, -lim);
27419 }
27420 else if (lim > 0)
27421 {
27422
27423
27424 if (precision > 0)
27425 lim = min (precision, lim);
27426
27427
27428
27429
27430 field_width = max (lim, field_width);
27431 }
27432 goto tail_recurse;
27433 }
27434 else if (STRINGP (car) || CONSP (car))
27435 FOR_EACH_TAIL_SAFE (elt)
27436 {
27437 if (0 < precision && precision <= n)
27438 break;
27439 n += display_mode_element (it, depth,
27440
27441
27442 (! CONSP (XCDR (elt))
27443 ? field_width - n
27444 : 0),
27445 precision - n, XCAR (elt),
27446 props, risky);
27447 }
27448 }
27449 break;
27450
27451 default:
27452 invalid:
27453 elt = build_string ("*invalid*");
27454 goto tail_recurse;
27455 }
27456
27457
27458 if (field_width > 0 && n < field_width)
27459 {
27460 switch (mode_line_target)
27461 {
27462 case MODE_LINE_NOPROP:
27463 case MODE_LINE_TITLE:
27464 n += store_mode_line_noprop ("", field_width - n, 0);
27465 break;
27466 case MODE_LINE_STRING:
27467 n += store_mode_line_string ("", Qnil, false, field_width - n, 0,
27468 Qnil);
27469 break;
27470 case MODE_LINE_DISPLAY:
27471 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
27472 0, 0, 0);
27473 break;
27474 }
27475 }
27476
27477 return n;
27478 }
27479
27480
27481
27482
27483
27484
27485
27486
27487
27488
27489
27490
27491
27492
27493
27494
27495
27496
27497
27498
27499 static int
27500 store_mode_line_string (const char *string, Lisp_Object lisp_string,
27501 bool copy_string,
27502 int field_width, int precision, Lisp_Object props)
27503 {
27504 ptrdiff_t len;
27505 int n = 0;
27506
27507 if (string != NULL)
27508 {
27509 len = strnlen (string, precision <= 0 ? SIZE_MAX : precision);
27510 lisp_string = make_string (string, len);
27511 if (NILP (props))
27512 props = mode_line_string_face_prop;
27513 else if (!NILP (mode_line_string_face))
27514 {
27515 Lisp_Object face = plist_get (props, Qface);
27516 props = Fcopy_sequence (props);
27517 if (NILP (face))
27518 face = mode_line_string_face;
27519 else
27520 face = list2 (face, mode_line_string_face);
27521 props = plist_put (props, Qface, face);
27522 }
27523 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27524 props, lisp_string);
27525 }
27526 else
27527 {
27528 len = SCHARS (lisp_string);
27529 if (precision > 0 && len > precision)
27530 {
27531 len = precision;
27532 lisp_string = Fsubstring (lisp_string, make_fixnum (0), make_fixnum (len));
27533 precision = -1;
27534 }
27535 if (!NILP (mode_line_string_face))
27536 {
27537 Lisp_Object face;
27538 if (NILP (props))
27539 props = Ftext_properties_at (make_fixnum (0), lisp_string);
27540 face = plist_get (props, Qface);
27541 if (NILP (face))
27542 face = mode_line_string_face;
27543 else
27544 face = list2 (face, mode_line_string_face);
27545 props = list2 (Qface, face);
27546 if (copy_string)
27547 lisp_string = Fcopy_sequence (lisp_string);
27548 }
27549 if (!NILP (props))
27550 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27551 props, lisp_string);
27552 }
27553
27554 if (len > 0)
27555 {
27556 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27557 n += len;
27558 }
27559
27560 if (field_width > len)
27561 {
27562 field_width -= len;
27563 lisp_string = Fmake_string (make_fixnum (field_width), make_fixnum (' '),
27564 Qnil);
27565 if (!NILP (props))
27566 Fadd_text_properties (make_fixnum (0), make_fixnum (field_width),
27567 props, lisp_string);
27568 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27569 n += field_width;
27570 }
27571
27572 return n;
27573 }
27574
27575
27576 DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
27577 1, 4, 0,
27578 doc:
27579
27580
27581
27582
27583
27584
27585
27586
27587
27588
27589
27590
27591
27592
27593
27594 )
27595 (Lisp_Object format, Lisp_Object face,
27596 Lisp_Object window, Lisp_Object buffer)
27597 {
27598 struct it it;
27599 int len;
27600 struct window *w;
27601 struct buffer *old_buffer = NULL;
27602 int face_id;
27603 bool no_props = FIXNUMP (face);
27604 specpdl_ref count = SPECPDL_INDEX ();
27605 Lisp_Object str;
27606 int string_start = 0;
27607
27608 w = decode_any_window (window);
27609 XSETWINDOW (window, w);
27610
27611 if (NILP (buffer))
27612 buffer = w->contents;
27613 CHECK_BUFFER (buffer);
27614
27615
27616
27617 if (NILP (format) || noninteractive)
27618 return empty_unibyte_string;
27619
27620 if (no_props)
27621 face = Qnil;
27622
27623 face_id = (NILP (face) || EQ (face, Qdefault)) ? DEFAULT_FACE_ID
27624 : EQ (face, Qt) ? (EQ (window, selected_window)
27625 ? MODE_LINE_ACTIVE_FACE_ID : MODE_LINE_INACTIVE_FACE_ID)
27626 : EQ (face, Qmode_line_active) ? MODE_LINE_ACTIVE_FACE_ID
27627 : EQ (face, Qmode_line_inactive) ? MODE_LINE_INACTIVE_FACE_ID
27628 : EQ (face, Qheader_line) ? HEADER_LINE_FACE_ID
27629 : EQ (face, Qtab_line) ? TAB_LINE_FACE_ID
27630 : EQ (face, Qtab_bar) ? TAB_BAR_FACE_ID
27631 : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
27632 : DEFAULT_FACE_ID;
27633
27634 old_buffer = current_buffer;
27635
27636
27637
27638 record_unwind_protect (unwind_format_mode_line,
27639 format_mode_line_unwind_data
27640 (XFRAME (WINDOW_FRAME (w)),
27641 old_buffer, selected_window, true));
27642 mode_line_proptrans_alist = Qnil;
27643
27644 Fselect_window (window, Qt);
27645 set_buffer_internal_1 (XBUFFER (buffer));
27646
27647 init_iterator (&it, w, -1, -1, NULL, face_id);
27648
27649 if (no_props)
27650 {
27651 mode_line_target = MODE_LINE_NOPROP;
27652 mode_line_string_face_prop = Qnil;
27653 mode_line_string_list = Qnil;
27654 string_start = MODE_LINE_NOPROP_LEN (0);
27655 }
27656 else
27657 {
27658 mode_line_target = MODE_LINE_STRING;
27659 mode_line_string_list = Qnil;
27660 mode_line_string_face = face;
27661 mode_line_string_face_prop
27662 = NILP (face) ? Qnil : list2 (Qface, face);
27663 }
27664
27665 push_kboard (FRAME_KBOARD (it.f));
27666 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27667 pop_kboard ();
27668
27669 if (no_props)
27670 {
27671 len = MODE_LINE_NOPROP_LEN (string_start);
27672 str = make_string (mode_line_noprop_buf + string_start, len);
27673 }
27674 else
27675 {
27676 mode_line_string_list = Fnreverse (mode_line_string_list);
27677 str = Fmapconcat (Qidentity, mode_line_string_list,
27678 empty_unibyte_string);
27679 }
27680
27681 return unbind_to (count, str);
27682 }
27683
27684
27685
27686
27687 static void
27688 pint2str (register char *buf, register int width, register ptrdiff_t d)
27689 {
27690 register char *p = buf;
27691
27692 if (d <= 0)
27693 *p++ = '0';
27694 else
27695 {
27696 while (d > 0)
27697 {
27698 *p++ = d % 10 + '0';
27699 d /= 10;
27700 }
27701 }
27702
27703 for (width -= (int) (p - buf); width > 0; --width)
27704 *p++ = ' ';
27705 *p-- = '\0';
27706 while (p > buf)
27707 {
27708 d = *buf;
27709 *buf++ = *p;
27710 *p-- = d;
27711 }
27712 }
27713
27714
27715
27716
27717
27718 static const char power_letter[] =
27719 {
27720 0,
27721 'k',
27722 'M',
27723 'G',
27724 'T',
27725 'P',
27726 'E',
27727 'Z',
27728 'Y'
27729 };
27730
27731 static void
27732 pint2hrstr (char *buf, int width, ptrdiff_t d)
27733 {
27734
27735
27736 ptrdiff_t quotient = d;
27737 int remainder = 0;
27738
27739 int tenths = -1;
27740 int exponent = 0;
27741
27742
27743 int length;
27744
27745 char * psuffix;
27746 char * p;
27747
27748 if (quotient >= 1000)
27749 {
27750
27751 do
27752 {
27753 remainder = quotient % 1000;
27754 quotient /= 1000;
27755 exponent++;
27756 }
27757 while (quotient >= 1000);
27758
27759
27760 if (quotient <= 9)
27761 {
27762 tenths = remainder / 100;
27763 if (remainder % 100 >= 50)
27764 {
27765 if (tenths < 9)
27766 tenths++;
27767 else
27768 {
27769 quotient++;
27770 if (quotient == 10)
27771 tenths = -1;
27772 else
27773 tenths = 0;
27774 }
27775 }
27776 }
27777 else
27778 if (remainder >= 500)
27779 {
27780 if (quotient < 999)
27781 quotient++;
27782 else
27783 {
27784 quotient = 1;
27785 exponent++;
27786 tenths = 0;
27787 }
27788 }
27789 }
27790
27791
27792 if (tenths == -1 && quotient <= 99)
27793 if (quotient <= 9)
27794 length = 1;
27795 else
27796 length = 2;
27797 else
27798 length = 3;
27799 p = psuffix = buf + max (width, length);
27800
27801
27802 *psuffix++ = power_letter[exponent];
27803 *psuffix = '\0';
27804
27805
27806 if (tenths >= 0)
27807 {
27808 *--p = '0' + tenths;
27809 *--p = '.';
27810 }
27811
27812
27813 do
27814 {
27815 int digit = quotient % 10;
27816 *--p = '0' + digit;
27817 }
27818 while ((quotient /= 10) != 0);
27819
27820
27821 while (buf < p)
27822 *--p = ' ';
27823 }
27824
27825
27826
27827
27828
27829 static unsigned char invalid_eol_type[] = "(*invalid*)";
27830
27831 static char *
27832 decode_mode_spec_coding (Lisp_Object coding_system, char *buf, bool eol_flag)
27833 {
27834 Lisp_Object val;
27835 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
27836 const unsigned char *eol_str;
27837 int eol_str_len;
27838
27839 Lisp_Object eoltype;
27840
27841 val = CODING_SYSTEM_SPEC (coding_system);
27842 eoltype = Qnil;
27843
27844 if (!VECTORP (val))
27845 {
27846 *buf++ = multibyte ? '-' : ' ';
27847 if (eol_flag)
27848 eoltype = eol_mnemonic_undecided;
27849
27850 }
27851 else
27852 {
27853 Lisp_Object attrs;
27854 Lisp_Object eolvalue;
27855
27856 attrs = AREF (val, 0);
27857 eolvalue = AREF (val, 2);
27858
27859 if (multibyte)
27860 buf += CHAR_STRING (XFIXNAT (CODING_ATTR_MNEMONIC (attrs)),
27861 (unsigned char *) buf);
27862 else
27863 *buf++ = ' ';
27864
27865 if (eol_flag)
27866 {
27867
27868
27869 if (NILP (eolvalue))
27870 eoltype = eol_mnemonic_undecided;
27871 else if (VECTORP (eolvalue))
27872 eoltype = eol_mnemonic_undecided;
27873 else
27874 eoltype = (EQ (eolvalue, Qunix)
27875 ? eol_mnemonic_unix
27876 : EQ (eolvalue, Qdos)
27877 ? eol_mnemonic_dos : eol_mnemonic_mac);
27878 }
27879 }
27880
27881 if (eol_flag)
27882 {
27883
27884 if (STRINGP (eoltype))
27885 {
27886 eol_str = SDATA (eoltype);
27887 eol_str_len = SBYTES (eoltype);
27888 }
27889 else if (CHARACTERP (eoltype))
27890 {
27891 int c = XFIXNAT (eoltype);
27892 return buf + CHAR_STRING (c, (unsigned char *) buf);
27893 }
27894 else
27895 {
27896 eol_str = invalid_eol_type;
27897 eol_str_len = sizeof (invalid_eol_type) - 1;
27898 }
27899 memcpy (buf, eol_str, eol_str_len);
27900 buf += eol_str_len;
27901 }
27902
27903 return buf;
27904 }
27905
27906
27907
27908
27909 static int
27910 percent99 (ptrdiff_t n, ptrdiff_t d)
27911 {
27912 int percent = (d - 1 + 100.0 * n) / d;
27913 return min (percent, 99);
27914 }
27915
27916
27917
27918
27919
27920
27921
27922
27923
27924 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
27925
27926 static const char *
27927 decode_mode_spec (struct window *w, register int c, int field_width,
27928 Lisp_Object *string)
27929 {
27930 Lisp_Object obj;
27931 struct frame *f = XFRAME (WINDOW_FRAME (w));
27932 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
27933
27934
27935
27936
27937
27938 int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
27939 struct buffer *b = current_buffer;
27940
27941 obj = Qnil;
27942 *string = Qnil;
27943
27944 switch (c)
27945 {
27946 case '*':
27947 if (!NILP (BVAR (b, read_only)))
27948 return "%";
27949 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
27950 return "*";
27951 return "-";
27952
27953 case '+':
27954
27955 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
27956 return "*";
27957 if (!NILP (BVAR (b, read_only)))
27958 return "%";
27959 return "-";
27960
27961 case '&':
27962
27963 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
27964 return "*";
27965 return "-";
27966
27967 case '%':
27968 return "%";
27969
27970 case '[':
27971 {
27972 int i;
27973 char *p;
27974
27975 if (command_loop_level > 5)
27976 return "[[[... ";
27977 p = decode_mode_spec_buf;
27978 for (i = 0; i < command_loop_level; i++)
27979 *p++ = '[';
27980 *p = 0;
27981 return decode_mode_spec_buf;
27982 }
27983
27984 case ']':
27985 {
27986 int i;
27987 char *p;
27988
27989 if (command_loop_level > 5)
27990 return " ...]]]";
27991 p = decode_mode_spec_buf;
27992 for (i = 0; i < command_loop_level; i++)
27993 *p++ = ']';
27994 *p = 0;
27995 return decode_mode_spec_buf;
27996 }
27997
27998 case '-':
27999 {
28000 register int i;
28001
28002
28003 if (mode_line_target == MODE_LINE_NOPROP
28004 || mode_line_target == MODE_LINE_STRING)
28005 return "--";
28006 if (field_width <= 0
28007 || field_width > sizeof (lots_of_dashes))
28008 {
28009 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
28010 decode_mode_spec_buf[i] = '-';
28011 decode_mode_spec_buf[i] = '\0';
28012 return decode_mode_spec_buf;
28013 }
28014 else
28015 return lots_of_dashes;
28016 }
28017
28018 case 'b':
28019 obj = BVAR (b, name);
28020 break;
28021
28022 case 'c':
28023 case 'C':
28024
28025
28026
28027
28028
28029 if (mode_line_target == MODE_LINE_TITLE)
28030 return "";
28031 else
28032 {
28033 ptrdiff_t col = current_column ();
28034 int disp_col = (c == 'C') ? col + 1 : col;
28035 w->column_number_displayed = col;
28036 pint2str (decode_mode_spec_buf, width, disp_col);
28037 return decode_mode_spec_buf;
28038 }
28039
28040 case 'e':
28041 #if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
28042 {
28043 if (NILP (Vmemory_full))
28044 return "";
28045 else
28046 return "!MEM FULL! ";
28047 }
28048 #else
28049 return "";
28050 #endif
28051
28052 case 'F':
28053
28054 if (!NILP (f->title))
28055 return SSDATA (f->title);
28056 if (f->explicit_name || ! FRAME_WINDOW_P (f))
28057 return SSDATA (f->name);
28058 return "Emacs";
28059
28060 case 'f':
28061 obj = BVAR (b, filename);
28062 break;
28063
28064 case 'i':
28065 {
28066 ptrdiff_t size = ZV - BEGV;
28067 pint2str (decode_mode_spec_buf, width, size);
28068 return decode_mode_spec_buf;
28069 }
28070
28071 case 'I':
28072 {
28073 ptrdiff_t size = ZV - BEGV;
28074 pint2hrstr (decode_mode_spec_buf, width, size);
28075 return decode_mode_spec_buf;
28076 }
28077
28078 case 'l':
28079 {
28080 ptrdiff_t startpos, startpos_byte, line, linepos, linepos_byte;
28081 ptrdiff_t topline, nlines, height;
28082 ptrdiff_t junk;
28083
28084
28085 if (mode_line_target == MODE_LINE_TITLE)
28086 return "";
28087
28088 startpos = marker_position (w->start);
28089 startpos_byte = marker_byte_position (w->start);
28090 height = WINDOW_TOTAL_LINES (w);
28091
28092
28093
28094
28095
28096
28097
28098
28099 if (!(BUF_BEGV_BYTE (b) <= startpos_byte
28100 && startpos_byte <= BUF_ZV_BYTE (b)))
28101 {
28102 startpos = BUF_BEGV (b);
28103 startpos_byte = BUF_BEGV_BYTE (b);
28104 w->base_line_pos = 0;
28105 w->base_line_number = 0;
28106 }
28107
28108
28109
28110 if (w->base_line_pos == -1)
28111 goto no_value;
28112
28113
28114 if (FIXNUMP (Vline_number_display_limit)
28115 && BUF_ZV (b) - BUF_BEGV (b) > XFIXNUM (Vline_number_display_limit))
28116 {
28117 w->base_line_pos = 0;
28118 w->base_line_number = 0;
28119 goto no_value;
28120 }
28121
28122 if (w->base_line_number > 0
28123 && w->base_line_pos > 0
28124 && w->base_line_pos <= startpos)
28125 {
28126 line = w->base_line_number;
28127 linepos = w->base_line_pos;
28128 linepos_byte = buf_charpos_to_bytepos (b, linepos);
28129 }
28130 else
28131 {
28132 line = 1;
28133 linepos = BUF_BEGV (b);
28134 linepos_byte = BUF_BEGV_BYTE (b);
28135 }
28136
28137
28138 nlines = display_count_lines (linepos_byte,
28139 startpos_byte,
28140 startpos, &junk);
28141
28142 topline = nlines + line;
28143
28144
28145
28146
28147
28148 if (startpos == BUF_BEGV (b))
28149 {
28150 w->base_line_number = topline;
28151 w->base_line_pos = BUF_BEGV (b);
28152 }
28153 else if (nlines < height + 25 || nlines > height * 3 + 50
28154 || linepos == BUF_BEGV (b))
28155 {
28156 ptrdiff_t limit = BUF_BEGV (b);
28157 ptrdiff_t limit_byte = BUF_BEGV_BYTE (b);
28158 ptrdiff_t position;
28159 ptrdiff_t distance
28160 = (line_number_display_limit_width < 0 ? 0
28161 : INT_MULTIPLY_WRAPV (line_number_display_limit_width,
28162 height * 2 + 30,
28163 &distance)
28164 ? PTRDIFF_MAX : distance);
28165
28166 if (startpos - distance > limit)
28167 {
28168 limit = startpos - distance;
28169 limit_byte = CHAR_TO_BYTE (limit);
28170 }
28171
28172 nlines = display_count_lines (startpos_byte,
28173 limit_byte,
28174 - (height * 2 + 30),
28175 &position);
28176
28177
28178
28179 if (position == limit_byte && limit == startpos - distance)
28180 {
28181 w->base_line_pos = -1;
28182 w->base_line_number = 0;
28183 goto no_value;
28184 }
28185
28186 w->base_line_number = topline - nlines;
28187 w->base_line_pos = BYTE_TO_CHAR (position);
28188 }
28189
28190
28191 nlines = display_count_lines (startpos_byte,
28192 PT_BYTE, PT, &junk);
28193
28194
28195 line_number_displayed = true;
28196
28197
28198 pint2str (decode_mode_spec_buf, width, topline + nlines);
28199 return decode_mode_spec_buf;
28200 no_value:
28201 {
28202 char *p = decode_mode_spec_buf;
28203 int pad = width - 2;
28204 while (pad-- > 0)
28205 *p++ = ' ';
28206 *p++ = '?';
28207 *p++ = '?';
28208 *p = '\0';
28209 return decode_mode_spec_buf;
28210 }
28211 }
28212 break;
28213
28214 case 'm':
28215 obj = BVAR (b, mode_name);
28216 break;
28217
28218 case 'n':
28219 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
28220 return " Narrow";
28221 break;
28222
28223
28224 case 'o':
28225 {
28226 ptrdiff_t toppos = marker_position (w->start);
28227 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28228 ptrdiff_t begv = BUF_BEGV (b);
28229 ptrdiff_t zv = BUF_ZV (b);
28230
28231 if (zv <= botpos)
28232 return toppos <= begv ? "All" : "Bottom";
28233 else if (toppos <= begv)
28234 return "Top";
28235 else
28236 {
28237 sprintf (decode_mode_spec_buf, "%2d%%",
28238 percent99 (toppos - begv, (toppos - begv) + (zv - botpos)));
28239 return decode_mode_spec_buf;
28240 }
28241 }
28242
28243
28244 case 'p':
28245 {
28246 ptrdiff_t pos = marker_position (w->start);
28247 ptrdiff_t begv = BUF_BEGV (b);
28248 ptrdiff_t zv = BUF_ZV (b);
28249
28250 if (w->window_end_pos <= BUF_Z (b) - zv)
28251 return pos <= begv ? "All" : "Bottom";
28252 else if (pos <= begv)
28253 return "Top";
28254 else
28255 {
28256 sprintf (decode_mode_spec_buf, "%2d%%",
28257 percent99 (pos - begv, zv - begv));
28258 return decode_mode_spec_buf;
28259 }
28260 }
28261
28262
28263 case 'P':
28264 {
28265 ptrdiff_t toppos = marker_position (w->start);
28266 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28267 ptrdiff_t begv = BUF_BEGV (b);
28268 ptrdiff_t zv = BUF_ZV (b);
28269
28270 if (zv <= botpos)
28271 return toppos <= begv ? "All" : "Bottom";
28272 else
28273 {
28274 sprintf (decode_mode_spec_buf,
28275 &"Top%2d%%"[begv < toppos ? sizeof "Top" - 1 : 0],
28276 percent99 (botpos - begv, zv - begv));
28277 return decode_mode_spec_buf;
28278 }
28279 }
28280
28281
28282
28283 case 'q':
28284 {
28285 ptrdiff_t toppos = marker_position (w->start);
28286 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28287 ptrdiff_t begv = BUF_BEGV (b);
28288 ptrdiff_t zv = BUF_ZV (b);
28289 int top_perc, bot_perc;
28290
28291 if ((toppos <= begv) && (zv <= botpos))
28292 return "All ";
28293
28294 top_perc = toppos <= begv ? 0 : percent99 (toppos - begv, zv - begv);
28295 bot_perc = zv <= botpos ? 100 : percent99 (botpos - begv, zv - begv);
28296
28297 if (top_perc == bot_perc)
28298 sprintf (decode_mode_spec_buf, "%d%%", top_perc);
28299 else
28300 sprintf (decode_mode_spec_buf, "%d-%d%%", top_perc, bot_perc);
28301
28302 return decode_mode_spec_buf;
28303 }
28304
28305 case 's':
28306
28307 obj = Fget_buffer_process (Fcurrent_buffer ());
28308 if (NILP (obj))
28309 return "no process";
28310 #ifndef MSDOS
28311 obj = Fsymbol_name (Fprocess_status (obj));
28312 #endif
28313 break;
28314
28315 case '@':
28316 {
28317 specpdl_ref count = inhibit_garbage_collection ();
28318 Lisp_Object curdir = BVAR (current_buffer, directory);
28319 Lisp_Object val = Qnil;
28320
28321 if (STRINGP (curdir))
28322 val = safe_call1 (intern ("file-remote-p"), curdir);
28323
28324 val = unbind_to (count, val);
28325
28326 if (NILP (val))
28327 return "-";
28328 else
28329 return "@";
28330 }
28331
28332 case 'z':
28333
28334 case 'Z':
28335
28336 {
28337 bool eol_flag = (c == 'Z');
28338 char *p = decode_mode_spec_buf;
28339
28340 if (! FRAME_WINDOW_P (f))
28341 {
28342
28343
28344 p = decode_mode_spec_coding (CODING_ID_NAME
28345 (FRAME_KEYBOARD_CODING (f)->id),
28346 p, false);
28347 p = decode_mode_spec_coding (CODING_ID_NAME
28348 (FRAME_TERMINAL_CODING (f)->id),
28349 p, false);
28350 }
28351 p = decode_mode_spec_coding (BVAR (b, buffer_file_coding_system),
28352 p, eol_flag);
28353
28354 #if false
28355 #ifdef subprocesses
28356 obj = Fget_buffer_process (Fcurrent_buffer ());
28357 if (PROCESSP (obj))
28358 {
28359 p = decode_mode_spec_coding
28360 (XPROCESS (obj)->decode_coding_system, p, eol_flag);
28361 p = decode_mode_spec_coding
28362 (XPROCESS (obj)->encode_coding_system, p, eol_flag);
28363 }
28364 #endif
28365 #endif
28366 *p = 0;
28367 return decode_mode_spec_buf;
28368 }
28369 }
28370
28371 if (STRINGP (obj))
28372 {
28373 *string = obj;
28374 return SSDATA (obj);
28375 }
28376 else
28377 return "";
28378 }
28379
28380
28381
28382
28383 ptrdiff_t
28384 count_lines (ptrdiff_t start_byte, ptrdiff_t end_byte)
28385 {
28386 ptrdiff_t ignored;
28387 return display_count_lines (start_byte, end_byte, ZV, &ignored);
28388 }
28389
28390
28391
28392
28393
28394
28395
28396
28397
28398
28399
28400 static ptrdiff_t
28401 display_count_lines (ptrdiff_t start_byte,
28402 ptrdiff_t limit_byte, ptrdiff_t count,
28403 ptrdiff_t *byte_pos_ptr)
28404 {
28405 register unsigned char *cursor;
28406 unsigned char *base;
28407
28408 register ptrdiff_t ceiling;
28409 register unsigned char *ceiling_addr;
28410 ptrdiff_t orig_count = count;
28411
28412
28413
28414 bool selective_display
28415 = (!NILP (BVAR (current_buffer, selective_display))
28416 && !FIXNUMP (BVAR (current_buffer, selective_display)));
28417
28418 if (count > 0)
28419 {
28420 while (start_byte < limit_byte)
28421 {
28422 ceiling = BUFFER_CEILING_OF (start_byte);
28423 ceiling = min (limit_byte - 1, ceiling);
28424 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
28425 base = (cursor = BYTE_POS_ADDR (start_byte));
28426
28427 do
28428 {
28429 if (selective_display)
28430 {
28431 while (*cursor != '\n' && *cursor != 015
28432 && ++cursor != ceiling_addr)
28433 continue;
28434 if (cursor == ceiling_addr)
28435 break;
28436 }
28437 else
28438 {
28439 cursor = memchr (cursor, '\n', ceiling_addr - cursor);
28440 if (! cursor)
28441 break;
28442 }
28443
28444 cursor++;
28445
28446 if (--count == 0)
28447 {
28448 start_byte += cursor - base;
28449 *byte_pos_ptr = start_byte;
28450 return orig_count;
28451 }
28452 }
28453 while (cursor < ceiling_addr);
28454
28455 start_byte += ceiling_addr - base;
28456 }
28457 }
28458 else
28459 {
28460 while (start_byte > limit_byte)
28461 {
28462 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
28463 ceiling = max (limit_byte, ceiling);
28464 ceiling_addr = BYTE_POS_ADDR (ceiling);
28465 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
28466 while (true)
28467 {
28468 if (selective_display)
28469 {
28470 while (--cursor >= ceiling_addr
28471 && *cursor != '\n' && *cursor != 015)
28472 continue;
28473 if (cursor < ceiling_addr)
28474 break;
28475 }
28476 else
28477 {
28478 cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr);
28479 if (! cursor)
28480 break;
28481 }
28482
28483 if (++count == 0)
28484 {
28485 start_byte += cursor - base + 1;
28486 *byte_pos_ptr = start_byte;
28487
28488
28489 return - orig_count - 1;
28490 }
28491 }
28492 start_byte += ceiling_addr - base;
28493 }
28494 }
28495
28496 *byte_pos_ptr = limit_byte;
28497
28498 if (count < 0)
28499 return - orig_count + count;
28500 return orig_count - count;
28501
28502 }
28503
28504
28505
28506
28507
28508
28509
28510
28511
28512
28513
28514
28515
28516
28517
28518
28519
28520
28521
28522
28523
28524
28525
28526
28527
28528
28529
28530
28531
28532
28533
28534
28535
28536
28537
28538
28539
28540
28541
28542
28543
28544
28545
28546
28547
28548 static int
28549 display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_string,
28550 ptrdiff_t face_string_pos, ptrdiff_t start, struct it *it,
28551 int field_width, int precision, int max_x, int multibyte)
28552 {
28553 int hpos_at_start = it->hpos;
28554 int saved_face_id = it->face_id;
28555 struct glyph_row *row = it->glyph_row;
28556 ptrdiff_t it_charpos;
28557
28558
28559
28560 reseat_to_string (it, NILP (lisp_string) ? string : NULL, lisp_string,
28561 start, precision, field_width, multibyte);
28562
28563 if (string && STRINGP (lisp_string))
28564
28565
28566 it->stop_charpos = it->end_charpos;
28567
28568
28569
28570 if (STRINGP (face_string))
28571 {
28572 ptrdiff_t endptr;
28573 struct face *face;
28574
28575 it->face_id
28576 = face_at_string_position (it->w, face_string, face_string_pos,
28577 0, &endptr, it->base_face_id, false, 0);
28578 face = FACE_FROM_ID (it->f, it->face_id);
28579 it->face_box_p = face->box != FACE_NO_BOX;
28580
28581
28582
28583
28584 if (NILP (lisp_string))
28585 {
28586 Lisp_Object display = Fget_text_property (make_fixnum (0), Qdisplay,
28587 face_string);
28588 if (!NILP (display))
28589 {
28590 Lisp_Object min_width = plist_get (display, Qmin_width);
28591 if (!NILP (min_width))
28592 display_min_width (it, 0, face_string, min_width);
28593 }
28594 }
28595 }
28596
28597
28598
28599 if (max_x <= 0)
28600 max_x = it->last_visible_x;
28601 else
28602 max_x = min (max_x, it->last_visible_x);
28603
28604
28605
28606 if (it->current_x < it->first_visible_x)
28607 move_it_in_display_line_to (it, 100000, it->first_visible_x,
28608 MOVE_TO_POS | MOVE_TO_X);
28609
28610 row->ascent = it->max_ascent;
28611 row->height = it->max_ascent + it->max_descent;
28612 row->phys_ascent = it->max_phys_ascent;
28613 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
28614 row->extra_line_spacing = it->max_extra_line_spacing;
28615
28616 if (STRINGP (it->string))
28617 it_charpos = IT_STRING_CHARPOS (*it);
28618 else
28619 it_charpos = IT_CHARPOS (*it);
28620
28621
28622
28623 while (it->current_x < max_x)
28624 {
28625 int x_before, x, n_glyphs_before, i, nglyphs;
28626
28627
28628 if (!get_next_display_element (it))
28629 break;
28630
28631
28632 x_before = it->current_x;
28633 n_glyphs_before = row->used[TEXT_AREA];
28634 PRODUCE_GLYPHS (it);
28635
28636 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
28637 i = 0;
28638 x = x_before;
28639 while (i < nglyphs)
28640 {
28641 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
28642
28643 if (it->line_wrap != TRUNCATE
28644 && x + glyph->pixel_width > max_x)
28645 {
28646
28647 if (CHAR_GLYPH_PADDING_P (*glyph))
28648 {
28649
28650 if (row->reversed_p)
28651 unproduce_glyphs (it, row->used[TEXT_AREA]
28652 - n_glyphs_before);
28653 row->used[TEXT_AREA] = n_glyphs_before;
28654 it->current_x = x_before;
28655 }
28656 else
28657 {
28658 if (row->reversed_p)
28659 unproduce_glyphs (it, row->used[TEXT_AREA]
28660 - (n_glyphs_before + i));
28661 row->used[TEXT_AREA] = n_glyphs_before + i;
28662 it->current_x = x;
28663 }
28664 break;
28665 }
28666 else if (x + glyph->pixel_width >= it->first_visible_x)
28667 {
28668
28669 ++it->hpos;
28670 if (x < it->first_visible_x)
28671 row->x = x - it->first_visible_x;
28672 }
28673 else
28674 {
28675
28676
28677 emacs_abort ();
28678 }
28679
28680 row->ascent = max (row->ascent, it->max_ascent);
28681 row->height = max (row->height, it->max_ascent + it->max_descent);
28682 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
28683 row->phys_height = max (row->phys_height,
28684 it->max_phys_ascent + it->max_phys_descent);
28685 row->extra_line_spacing = max (row->extra_line_spacing,
28686 it->max_extra_line_spacing);
28687 x += glyph->pixel_width;
28688 ++i;
28689 }
28690
28691
28692 if (i < nglyphs)
28693 break;
28694
28695
28696 if (ITERATOR_AT_END_OF_LINE_P (it))
28697 {
28698 it->continuation_lines_width = 0;
28699 break;
28700 }
28701
28702 set_iterator_to_next (it, true);
28703 if (STRINGP (it->string))
28704 it_charpos = IT_STRING_CHARPOS (*it);
28705 else
28706 it_charpos = IT_CHARPOS (*it);
28707
28708
28709 if (it->line_wrap == TRUNCATE
28710 && it->current_x >= it->last_visible_x)
28711 {
28712
28713
28714 if (it_charpos < it->string_nchars)
28715 {
28716 if (!FRAME_WINDOW_P (it->f))
28717 {
28718 int ii, n;
28719
28720 if (it->current_x > it->last_visible_x)
28721 {
28722 if (!row->reversed_p)
28723 {
28724 for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii)
28725 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28726 break;
28727 }
28728 else
28729 {
28730 for (ii = 0; ii < row->used[TEXT_AREA]; ii++)
28731 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28732 break;
28733 unproduce_glyphs (it, ii + 1);
28734 ii = row->used[TEXT_AREA] - (ii + 1);
28735 }
28736 for (n = row->used[TEXT_AREA]; ii < n; ++ii)
28737 {
28738 row->used[TEXT_AREA] = ii;
28739 produce_special_glyphs (it, IT_TRUNCATION);
28740 }
28741 }
28742 produce_special_glyphs (it, IT_TRUNCATION);
28743 }
28744 row->truncated_on_right_p = true;
28745 }
28746 break;
28747 }
28748 }
28749
28750
28751 if (it->first_visible_x
28752 && it_charpos > 0)
28753 {
28754 if (!FRAME_WINDOW_P (it->f)
28755 || (row->reversed_p
28756 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
28757 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
28758 insert_left_trunc_glyphs (it);
28759 row->truncated_on_left_p = true;
28760 }
28761
28762 it->face_id = saved_face_id;
28763
28764
28765 return it->hpos - hpos_at_start;
28766 }
28767
28768
28769
28770
28771
28772
28773
28774
28775
28776
28777
28778 int
28779 invisible_prop (Lisp_Object propval, Lisp_Object list)
28780 {
28781 Lisp_Object tail, proptail;
28782
28783 for (tail = list; CONSP (tail); tail = XCDR (tail))
28784 {
28785 register Lisp_Object tem;
28786 tem = XCAR (tail);
28787 if (EQ (propval, tem))
28788 return 1;
28789 if (CONSP (tem) && EQ (propval, XCAR (tem)))
28790 return NILP (XCDR (tem)) ? 1 : 2;
28791 }
28792
28793 if (CONSP (propval))
28794 {
28795 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
28796 {
28797 Lisp_Object propelt;
28798 propelt = XCAR (proptail);
28799 for (tail = list; CONSP (tail); tail = XCDR (tail))
28800 {
28801 register Lisp_Object tem;
28802 tem = XCAR (tail);
28803 if (EQ (propelt, tem))
28804 return 1;
28805 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
28806 return NILP (XCDR (tem)) ? 1 : 2;
28807 }
28808 }
28809 }
28810
28811 return 0;
28812 }
28813
28814 DEFUN ("invisible-p", Finvisible_p, Sinvisible_p, 1, 1, 0,
28815 doc:
28816
28817
28818
28819
28820
28821
28822
28823
28824
28825
28826
28827 )
28828 (Lisp_Object pos)
28829 {
28830 Lisp_Object prop
28831 = (FIXNATP (pos) || MARKERP (pos)
28832 ? Fget_char_property (pos, Qinvisible, Qnil)
28833 : pos);
28834 int invis = TEXT_PROP_MEANS_INVISIBLE (prop);
28835 return (invis == 0 ? Qnil
28836 : invis == 1 ? Qt
28837 : make_fixnum (invis));
28838 }
28839
28840
28841
28842
28843
28844
28845
28846
28847
28848
28849
28850
28851
28852
28853
28854
28855
28856
28857
28858
28859
28860
28861
28862
28863
28864
28865
28866
28867
28868
28869
28870
28871
28872
28873
28874
28875
28876
28877
28878
28879
28880
28881
28882
28883
28884
28885
28886
28887
28888
28889
28890
28891
28892
28893
28894
28895
28896
28897
28898
28899
28900
28901
28902
28903
28904
28905
28906
28907
28908
28909
28910
28911
28912
28913
28914
28915
28916
28917
28918
28919
28920 static bool
28921 calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
28922 struct font *font, bool width_p, int *align_to)
28923 {
28924
28925
28926
28927
28928 int lnum_pixel_width = it->line_number_produced_p ? it->lnum_pixel_width : 0;
28929 double pixels;
28930
28931 # define OK_PIXELS(val) (*res = (val), true)
28932 # define OK_ALIGN_TO(val) (*align_to = (val), true)
28933
28934 if (NILP (prop))
28935 return OK_PIXELS (0);
28936
28937 eassert (FRAME_LIVE_P (it->f));
28938
28939 if (SYMBOLP (prop))
28940 {
28941 if (SCHARS (SYMBOL_NAME (prop)) == 2)
28942 {
28943 char *unit = SSDATA (SYMBOL_NAME (prop));
28944
28945
28946 if (unit[0] == 'i' && unit[1] == 'n')
28947 pixels = 1.0;
28948 else if (unit[0] == 'm' && unit[1] == 'm')
28949 pixels = 25.4;
28950 else if (unit[0] == 'c' && unit[1] == 'm')
28951 pixels = 2.54;
28952 else
28953 pixels = 0;
28954 if (pixels > 0)
28955 {
28956 double ppi = (width_p ? FRAME_RES_X (it->f)
28957 : FRAME_RES_Y (it->f));
28958
28959 if (ppi > 0)
28960 return OK_PIXELS (ppi / pixels);
28961 return false;
28962 }
28963 }
28964
28965 #ifdef HAVE_WINDOW_SYSTEM
28966
28967 if (EQ (prop, Qheight))
28968 return OK_PIXELS (font
28969 ? normal_char_height (font, -1)
28970 : FRAME_LINE_HEIGHT (it->f));
28971
28972 if (EQ (prop, Qwidth))
28973 return OK_PIXELS (font
28974 ? FONT_WIDTH (font)
28975 : FRAME_COLUMN_WIDTH (it->f));
28976 #else
28977 if (EQ (prop, Qheight) || EQ (prop, Qwidth))
28978 return OK_PIXELS (1);
28979 #endif
28980
28981
28982 if (EQ (prop, Qtext))
28983 return OK_PIXELS (width_p
28984 ? (window_box_width (it->w, TEXT_AREA)
28985 - lnum_pixel_width)
28986 : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
28987
28988
28989
28990
28991 if (align_to && *align_to < 0)
28992 {
28993 *res = 0;
28994
28995 if (EQ (prop, Qleft))
28996 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
28997 + lnum_pixel_width);
28998
28999 if (EQ (prop, Qright))
29000 return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
29001
29002 if (EQ (prop, Qcenter))
29003 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29004 + lnum_pixel_width
29005 + window_box_width (it->w, TEXT_AREA) / 2);
29006
29007 if (EQ (prop, Qleft_fringe))
29008 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29009 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w)
29010 : window_box_right_offset (it->w, LEFT_MARGIN_AREA));
29011
29012 if (EQ (prop, Qright_fringe))
29013 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29014 ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29015 : window_box_right_offset (it->w, TEXT_AREA));
29016
29017 if (EQ (prop, Qleft_margin))
29018 return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA));
29019
29020 if (EQ (prop, Qright_margin))
29021 return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA));
29022
29023 if (EQ (prop, Qscroll_bar))
29024 return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
29025 ? 0
29026 : (window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29027 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29028 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29029 : 0)));
29030 }
29031 else
29032 {
29033
29034 if (EQ (prop, Qleft_fringe))
29035 return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
29036 if (EQ (prop, Qright_fringe))
29037 return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
29038 if (EQ (prop, Qleft_margin))
29039 return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
29040 if (EQ (prop, Qright_margin))
29041 return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
29042 if (EQ (prop, Qscroll_bar))
29043 return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
29044 }
29045
29046 prop = buffer_local_value (prop, it->w->contents);
29047 if (BASE_EQ (prop, Qunbound))
29048 prop = Qnil;
29049 }
29050
29051 if (NUMBERP (prop))
29052 {
29053 int base_unit = (width_p
29054 ? FRAME_COLUMN_WIDTH (it->f)
29055 : FRAME_LINE_HEIGHT (it->f));
29056 if (width_p && align_to && *align_to < 0)
29057 return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width);
29058 return OK_PIXELS (XFLOATINT (prop) * base_unit);
29059 }
29060
29061 if (CONSP (prop))
29062 {
29063 Lisp_Object car = XCAR (prop);
29064 Lisp_Object cdr = XCDR (prop);
29065
29066 if (SYMBOLP (car))
29067 {
29068 #ifdef HAVE_WINDOW_SYSTEM
29069
29070 if (FRAME_WINDOW_P (it->f)
29071 && valid_image_p (prop))
29072 {
29073 ptrdiff_t id = lookup_image (it->f, prop, it->face_id);
29074 struct image *img = IMAGE_FROM_ID (it->f, id);
29075
29076 return OK_PIXELS (width_p ? img->width : img->height);
29077 }
29078
29079 if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
29080 {
29081
29082 return OK_PIXELS (100);
29083 }
29084 #endif
29085
29086
29087 if (EQ (car, Qplus) || EQ (car, Qminus))
29088 {
29089 bool first = true;
29090 double px;
29091
29092 pixels = 0;
29093 while (CONSP (cdr))
29094 {
29095 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr),
29096 font, width_p, align_to))
29097 return false;
29098 if (first)
29099 pixels = (EQ (car, Qplus) ? px : -px), first = false;
29100 else
29101 pixels += px;
29102 cdr = XCDR (cdr);
29103 }
29104 if (EQ (car, Qminus))
29105 pixels = -pixels;
29106 return OK_PIXELS (pixels);
29107 }
29108
29109 car = buffer_local_value (car, it->w->contents);
29110 if (BASE_EQ (car, Qunbound))
29111 car = Qnil;
29112 }
29113
29114
29115 if (NUMBERP (car))
29116 {
29117 double fact;
29118 int offset =
29119 width_p && align_to && *align_to < 0 ? lnum_pixel_width : 0;
29120 pixels = XFLOATINT (car);
29121 if (NILP (cdr))
29122 return OK_PIXELS (pixels + offset);
29123 if (calc_pixel_width_or_height (&fact, it, cdr,
29124 font, width_p, align_to))
29125 return OK_PIXELS (pixels * fact + offset);
29126 return false;
29127 }
29128
29129 return false;
29130 }
29131
29132 return false;
29133 }
29134
29135 void
29136 get_font_ascent_descent (struct font *font, int *ascent, int *descent)
29137 {
29138 #ifdef HAVE_WINDOW_SYSTEM
29139 normal_char_ascent_descent (font, -1, ascent, descent);
29140 #else
29141 *ascent = 1;
29142 *descent = 0;
29143 #endif
29144 }
29145
29146
29147
29148
29149
29150
29151 #ifdef HAVE_WINDOW_SYSTEM
29152
29153 #ifdef GLYPH_DEBUG
29154
29155 extern void dump_glyph_string (struct glyph_string *) EXTERNALLY_VISIBLE;
29156 void
29157 dump_glyph_string (struct glyph_string *s)
29158 {
29159 fputs ("glyph string\n", stderr);
29160 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
29161 s->x, s->y, s->width, s->height);
29162 fprintf (stderr, " ybase = %d\n", s->ybase);
29163 fprintf (stderr, " hl = %u\n", s->hl);
29164 fprintf (stderr, " left overhang = %d, right = %d\n",
29165 s->left_overhang, s->right_overhang);
29166 fprintf (stderr, " nchars = %d\n", s->nchars);
29167 fprintf (stderr, " extends to end of line = %d\n",
29168 s->extends_to_end_of_line_p);
29169 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
29170 fprintf (stderr, " bg width = %d\n", s->background_width);
29171 }
29172
29173 #endif
29174
29175
29176
29177
29178
29179
29180
29181
29182
29183 #ifdef HAVE_NTGUI
29184
29185
29186
29187
29188
29189 # define ALLOCATE_HDC(hdc, f) \
29190 Lisp_Object prev_quit = Vinhibit_quit; \
29191 Vinhibit_quit = Qt; \
29192 HDC hdc = get_frame_dc ((f))
29193 # define RELEASE_HDC(hdc, f) \
29194 release_frame_dc ((f), (hdc)); \
29195 Vinhibit_quit = prev_quit
29196 #else
29197 # define ALLOCATE_HDC(hdc, f)
29198 # define RELEASE_HDC(hdc, f)
29199 #endif
29200
29201 static void
29202 init_glyph_string (struct glyph_string *s,
29203 #ifdef HAVE_NTGUI
29204 HDC hdc,
29205 #endif
29206 unsigned *char2b, struct window *w, struct glyph_row *row,
29207 enum glyph_row_area area, int start, enum draw_glyphs_face hl)
29208 {
29209 memset (s, 0, sizeof *s);
29210 s->w = w;
29211 s->f = XFRAME (w->frame);
29212 #ifdef HAVE_NTGUI
29213 s->hdc = hdc;
29214 #endif
29215 s->char2b = char2b;
29216 s->hl = hl;
29217 s->row = row;
29218 s->area = area;
29219 s->first_glyph = row->glyphs[area] + start;
29220 s->height = row->height;
29221 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
29222 s->ybase = s->y + row->ascent;
29223 }
29224
29225
29226
29227
29228
29229 static void
29230 append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29231 struct glyph_string *h, struct glyph_string *t)
29232 {
29233 if (h)
29234 {
29235 if (*head)
29236 (*tail)->next = h;
29237 else
29238 *head = h;
29239 h->prev = *tail;
29240 *tail = t;
29241 }
29242 }
29243
29244
29245
29246
29247
29248
29249 static void
29250 prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29251 struct glyph_string *h, struct glyph_string *t)
29252 {
29253 if (h)
29254 {
29255 if (*head)
29256 (*head)->prev = t;
29257 else
29258 *tail = t;
29259 t->next = *head;
29260 *head = h;
29261 }
29262 }
29263
29264
29265
29266
29267
29268 static void
29269 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
29270 struct glyph_string *s)
29271 {
29272 s->next = s->prev = NULL;
29273 append_glyph_string_lists (head, tail, s, s);
29274 }
29275
29276
29277
29278
29279
29280
29281
29282
29283 static struct face *
29284 get_char_face_and_encoding (struct frame *f, int c, int face_id,
29285 unsigned *char2b, bool display_p)
29286 {
29287 struct face *face = FACE_FROM_ID (f, face_id);
29288 unsigned code = 0;
29289
29290 if (face->font)
29291 {
29292 code = face->font->driver->encode_char (face->font, c);
29293
29294 if (code == FONT_INVALID_CODE)
29295 code = 0;
29296 }
29297
29298 *char2b = code & 0xFFFF;
29299
29300
29301 #ifdef HAVE_X_WINDOWS
29302 if (display_p)
29303 #endif
29304 {
29305 eassert (face != NULL);
29306 prepare_face_for_display (f, face);
29307 }
29308
29309 return face;
29310 }
29311
29312
29313
29314
29315
29316
29317 static struct face *
29318 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
29319 unsigned *char2b)
29320 {
29321 struct face *face;
29322 unsigned code = 0;
29323
29324 eassert (glyph->type == CHAR_GLYPH);
29325 face = FACE_FROM_ID (f, glyph->face_id);
29326
29327
29328 prepare_face_for_display (f, face);
29329
29330 if (face->font)
29331 {
29332 if (CHAR_BYTE8_P (glyph->u.ch))
29333 code = CHAR_TO_BYTE8 (glyph->u.ch);
29334 else
29335 code = face->font->driver->encode_char (face->font, glyph->u.ch);
29336
29337 if (code == FONT_INVALID_CODE)
29338 code = 0;
29339 }
29340
29341
29342 *char2b = code & 0xFFFF;
29343 return face;
29344 }
29345
29346
29347
29348
29349
29350 static bool
29351 get_char_glyph_code (int c, struct font *font, unsigned *char2b)
29352 {
29353 unsigned code;
29354
29355 if (CHAR_BYTE8_P (c))
29356 code = CHAR_TO_BYTE8 (c);
29357 else
29358 code = font->driver->encode_char (font, c);
29359
29360 if (code == FONT_INVALID_CODE)
29361 return false;
29362
29363
29364 *char2b = code & 0xFFFF;
29365 return true;
29366 }
29367
29368
29369
29370
29371
29372
29373
29374
29375
29376
29377
29378
29379 static int
29380 fill_composite_glyph_string (struct glyph_string *s, struct face *base_face,
29381 int overlaps)
29382 {
29383 int i;
29384
29385
29386
29387 struct face *face;
29388
29389 eassert (s);
29390
29391 s->for_overlaps = overlaps;
29392 s->face = NULL;
29393 s->font = NULL;
29394 for (i = s->cmp_from; i < s->cmp->glyph_len; i++)
29395 {
29396 int c = COMPOSITION_GLYPH (s->cmp, i);
29397
29398
29399
29400 if (c != '\t')
29401 {
29402 int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
29403 -1, Qnil);
29404
29405 face = get_char_face_and_encoding (s->f, c, face_id,
29406 s->char2b + i, true);
29407 if (face)
29408 {
29409 if (! s->face)
29410 {
29411 s->face = face;
29412 s->font = s->face->font;
29413 }
29414 else if (s->face != face)
29415 break;
29416 }
29417 }
29418 ++s->nchars;
29419 }
29420 s->cmp_to = i;
29421
29422 if (s->face == NULL)
29423 {
29424 s->face = base_face->ascii_face;
29425 s->font = s->face->font;
29426 }
29427
29428 if (s->hl == DRAW_MOUSE_FACE
29429 || (s->hl == DRAW_CURSOR
29430 && MATRIX_ROW (s->w->current_matrix,
29431 s->w->phys_cursor.vpos)->mouse_face_p
29432 && cursor_in_mouse_face_p (s->w)))
29433 {
29434 int c = COMPOSITION_GLYPH (s->cmp, 0);
29435 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29436 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29437 if (!s->face)
29438 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29439
29440 s->face = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face, c, -1, Qnil));
29441 prepare_face_for_display (s->f, s->face);
29442 }
29443
29444
29445
29446 s->width = s->first_glyph->pixel_width;
29447
29448
29449
29450
29451
29452 if (s->font == NULL)
29453 {
29454 s->font_not_found_p = true;
29455 s->font = FRAME_FONT (s->f);
29456 }
29457
29458
29459 s->ybase += s->first_glyph->voffset;
29460
29461 return s->cmp_to;
29462 }
29463
29464 static int
29465 fill_gstring_glyph_string (struct glyph_string *s, int face_id,
29466 int start, int end, int overlaps)
29467 {
29468 struct glyph *glyph, *last;
29469 int voffset;
29470 Lisp_Object lgstring;
29471 int i;
29472 bool glyph_not_available_p;
29473
29474 s->for_overlaps = overlaps;
29475 glyph = s->row->glyphs[s->area] + start;
29476 last = s->row->glyphs[s->area] + end;
29477 voffset = glyph->voffset;
29478 glyph_not_available_p = glyph->glyph_not_available_p;
29479 s->cmp_id = glyph->u.cmp.id;
29480 s->cmp_from = glyph->slice.cmp.from;
29481 s->cmp_to = glyph->slice.cmp.to + 1;
29482 if (s->hl == DRAW_MOUSE_FACE
29483 || (s->hl == DRAW_CURSOR
29484 && MATRIX_ROW (s->w->current_matrix,
29485 s->w->phys_cursor.vpos)->mouse_face_p
29486 && cursor_in_mouse_face_p (s->w)))
29487 {
29488 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29489 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29490 if (!s->face)
29491 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29492 prepare_face_for_display (s->f, s->face);
29493 }
29494 else
29495 s->face = FACE_FROM_ID (s->f, face_id);
29496 lgstring = composition_gstring_from_id (s->cmp_id);
29497 s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
29498
29499
29500 s->width = s->first_glyph->pixel_width;
29501 glyph++;
29502 while (glyph < last
29503 && glyph->u.cmp.automatic
29504 && glyph->u.cmp.id == s->cmp_id
29505 && glyph->face_id == face_id
29506 && s->cmp_to == glyph->slice.cmp.from
29507 && glyph->glyph_not_available_p == glyph_not_available_p)
29508 {
29509 s->width += glyph->pixel_width;
29510 s->cmp_to = (glyph++)->slice.cmp.to + 1;
29511 }
29512
29513 for (i = s->cmp_from; i < s->cmp_to; i++)
29514 {
29515 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
29516 unsigned code = LGLYPH_CODE (lglyph);
29517
29518
29519 s->char2b[i] = code & 0xFFFF;
29520 }
29521
29522
29523
29524
29525 if (glyph_not_available_p)
29526 s->font_not_found_p = true;
29527
29528
29529 s->ybase += voffset;
29530
29531 return glyph - s->row->glyphs[s->area];
29532 }
29533
29534
29535
29536
29537
29538
29539
29540 static int
29541 fill_glyphless_glyph_string (struct glyph_string *s, int face_id,
29542 int start, int end, int overlaps)
29543 {
29544 struct glyph *glyph, *last;
29545 int voffset;
29546
29547 eassert (s->first_glyph->type == GLYPHLESS_GLYPH);
29548 s->for_overlaps = overlaps;
29549 glyph = s->row->glyphs[s->area] + start;
29550 last = s->row->glyphs[s->area] + end;
29551 voffset = glyph->voffset;
29552 s->face = FACE_FROM_ID (s->f, face_id);
29553 s->font = s->face->font ? s->face->font : FRAME_FONT (s->f);
29554 if (s->hl == DRAW_MOUSE_FACE
29555 || (s->hl == DRAW_CURSOR
29556 && MATRIX_ROW (s->w->current_matrix,
29557 s->w->phys_cursor.vpos)->mouse_face_p
29558 && cursor_in_mouse_face_p (s->w)))
29559 {
29560 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29561 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29562 if (!s->face)
29563 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29564 prepare_face_for_display (s->f, s->face);
29565 }
29566 s->nchars = 1;
29567 s->width = glyph->pixel_width;
29568 glyph++;
29569 while (glyph < last
29570 && glyph->type == GLYPHLESS_GLYPH
29571 && glyph->voffset == voffset
29572 && glyph->face_id == face_id)
29573 {
29574 s->nchars++;
29575 s->width += glyph->pixel_width;
29576 glyph++;
29577 }
29578 s->ybase += voffset;
29579 return glyph - s->row->glyphs[s->area];
29580 }
29581
29582
29583
29584
29585
29586
29587
29588
29589
29590
29591
29592 static int
29593 fill_glyph_string (struct glyph_string *s, int face_id,
29594 int start, int end, int overlaps)
29595 {
29596 struct glyph *glyph, *last;
29597 int voffset;
29598 bool glyph_not_available_p;
29599
29600 eassert (s->f == XFRAME (s->w->frame));
29601 eassert (s->nchars == 0);
29602 eassert (start >= 0 && end > start);
29603
29604 s->for_overlaps = overlaps;
29605 glyph = s->row->glyphs[s->area] + start;
29606 last = s->row->glyphs[s->area] + end;
29607 voffset = glyph->voffset;
29608 s->padding_p = glyph->padding_p;
29609 glyph_not_available_p = glyph->glyph_not_available_p;
29610
29611 while (glyph < last
29612 && glyph->type == CHAR_GLYPH
29613 && glyph->voffset == voffset
29614
29615 && glyph->face_id == face_id
29616 && glyph->glyph_not_available_p == glyph_not_available_p)
29617 {
29618 s->face = get_glyph_face_and_encoding (s->f, glyph,
29619 s->char2b + s->nchars);
29620 ++s->nchars;
29621 eassert (s->nchars <= end - start);
29622 s->width += glyph->pixel_width;
29623 if (glyph++->padding_p != s->padding_p)
29624 break;
29625 }
29626
29627 s->font = s->face->font;
29628
29629 if (s->hl == DRAW_MOUSE_FACE
29630 || (s->hl == DRAW_CURSOR
29631 && MATRIX_ROW (s->w->current_matrix,
29632 s->w->phys_cursor.vpos)->mouse_face_p
29633 && cursor_in_mouse_face_p (s->w)))
29634 {
29635 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29636 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29637 if (!s->face)
29638 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29639 s->face
29640 = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face,
29641 s->first_glyph->u.ch, -1, Qnil));
29642 prepare_face_for_display (s->f, s->face);
29643 }
29644
29645
29646
29647
29648
29649 if (s->font == NULL || glyph_not_available_p)
29650 {
29651 s->font_not_found_p = true;
29652 s->font = FRAME_FONT (s->f);
29653 }
29654
29655
29656 s->ybase += voffset;
29657
29658 eassert (s->face && s->face->gc);
29659 return glyph - s->row->glyphs[s->area];
29660 }
29661
29662
29663
29664
29665 static void
29666 fill_image_glyph_string (struct glyph_string *s)
29667 {
29668 eassert (s->first_glyph->type == IMAGE_GLYPH);
29669 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
29670 eassert (s->img);
29671 s->slice = s->first_glyph->slice.img;
29672 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29673 s->font = s->face->font;
29674 if (s->hl == DRAW_MOUSE_FACE
29675 || (s->hl == DRAW_CURSOR
29676 && MATRIX_ROW (s->w->current_matrix,
29677 s->w->phys_cursor.vpos)->mouse_face_p
29678 && cursor_in_mouse_face_p (s->w)))
29679 {
29680 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29681 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29682 if (!s->face)
29683 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29684 prepare_face_for_display (s->f, s->face);
29685 }
29686 s->width = s->first_glyph->pixel_width;
29687
29688
29689 s->ybase += s->first_glyph->voffset;
29690 }
29691
29692
29693 #ifdef HAVE_XWIDGETS
29694 static void
29695 fill_xwidget_glyph_string (struct glyph_string *s)
29696 {
29697 eassert (s->first_glyph->type == XWIDGET_GLYPH);
29698 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29699 s->font = s->face->font;
29700 if (s->hl == DRAW_MOUSE_FACE
29701 || (s->hl == DRAW_CURSOR
29702 && MATRIX_ROW (s->w->current_matrix,
29703 s->w->phys_cursor.vpos)->mouse_face_p
29704 && cursor_in_mouse_face_p (s->w)))
29705 {
29706 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29707 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29708 if (!s->face)
29709 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29710 prepare_face_for_display (s->f, s->face);
29711 }
29712 s->width = s->first_glyph->pixel_width;
29713 s->ybase += s->first_glyph->voffset;
29714 s->xwidget = xwidget_from_id (s->first_glyph->u.xwidget);
29715 }
29716 #endif
29717
29718
29719
29720
29721
29722
29723
29724 static int
29725 fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
29726 {
29727 struct glyph *glyph, *last;
29728 int voffset, face_id;
29729
29730 eassert (s->first_glyph->type == STRETCH_GLYPH);
29731
29732 glyph = s->row->glyphs[s->area] + start;
29733 last = s->row->glyphs[s->area] + end;
29734 face_id = glyph->face_id;
29735 s->face = FACE_FROM_ID (s->f, face_id);
29736 s->font = s->face->font;
29737 if (s->hl == DRAW_MOUSE_FACE
29738 || (s->hl == DRAW_CURSOR
29739 && MATRIX_ROW (s->w->current_matrix,
29740 s->w->phys_cursor.vpos)->mouse_face_p
29741 && cursor_in_mouse_face_p (s->w)))
29742 {
29743 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29744 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29745 if (!s->face)
29746 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29747 prepare_face_for_display (s->f, s->face);
29748 }
29749 s->width = glyph->pixel_width;
29750 s->nchars = 1;
29751 voffset = glyph->voffset;
29752
29753 for (++glyph;
29754 (glyph < last
29755 && glyph->type == STRETCH_GLYPH
29756 && glyph->voffset == voffset
29757 && glyph->face_id == face_id);
29758 ++glyph)
29759 s->width += glyph->pixel_width;
29760
29761
29762 s->ybase += voffset;
29763
29764
29765
29766 eassert (s->face);
29767 return glyph - s->row->glyphs[s->area];
29768 }
29769
29770 static struct font_metrics *
29771 get_per_char_metric (struct font *font, const unsigned *char2b)
29772 {
29773 static struct font_metrics metrics;
29774
29775 if (! font)
29776 return NULL;
29777 if (*char2b == FONT_INVALID_CODE)
29778 return NULL;
29779
29780 font->driver->text_extents (font, char2b, 1, &metrics);
29781 return &metrics;
29782 }
29783
29784
29785
29786
29787
29788
29789
29790 static void
29791 normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
29792 {
29793 *ascent = FONT_BASE (font);
29794 *descent = FONT_DESCENT (font);
29795
29796 if (FONT_TOO_HIGH (font))
29797 {
29798 unsigned char2b;
29799
29800
29801
29802 if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
29803 {
29804 struct font_metrics *pcm = get_per_char_metric (font, &char2b);
29805 eassume (pcm);
29806
29807 if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
29808 {
29809
29810
29811
29812 *ascent = pcm->ascent + 1;
29813 *descent = pcm->descent + 1;
29814 }
29815 }
29816 }
29817 }
29818
29819
29820
29821
29822
29823
29824 static int
29825 normal_char_height (struct font *font, int c)
29826 {
29827 int ascent, descent;
29828
29829 normal_char_ascent_descent (font, c, &ascent, &descent);
29830
29831 return ascent + descent;
29832 }
29833
29834
29835
29836
29837
29838
29839 void
29840 gui_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *right)
29841 {
29842 *left = *right = 0;
29843
29844 if (glyph->type == CHAR_GLYPH)
29845 {
29846 unsigned char2b;
29847 struct face *face = get_glyph_face_and_encoding (f, glyph, &char2b);
29848 if (face->font)
29849 {
29850 struct font_metrics *pcm = get_per_char_metric (face->font, &char2b);
29851 if (pcm)
29852 {
29853 if (pcm->rbearing > pcm->width)
29854 *right = pcm->rbearing - pcm->width;
29855 if (pcm->lbearing < 0)
29856 *left = -pcm->lbearing;
29857 }
29858 }
29859 }
29860 else if (glyph->type == COMPOSITE_GLYPH)
29861 {
29862 if (! glyph->u.cmp.automatic)
29863 {
29864 struct composition *cmp = composition_table[glyph->u.cmp.id];
29865
29866 if (cmp->rbearing > cmp->pixel_width)
29867 *right = cmp->rbearing - cmp->pixel_width;
29868 if (cmp->lbearing < 0)
29869 *left = - cmp->lbearing;
29870 }
29871 else
29872 {
29873 Lisp_Object gstring = composition_gstring_from_id (glyph->u.cmp.id);
29874 struct font_metrics metrics;
29875
29876 composition_gstring_width (gstring, glyph->slice.cmp.from,
29877 glyph->slice.cmp.to + 1, &metrics);
29878 if (metrics.rbearing > metrics.width)
29879 *right = metrics.rbearing - metrics.width;
29880 if (metrics.lbearing < 0)
29881 *left = - metrics.lbearing;
29882 }
29883 }
29884 }
29885
29886
29887
29888
29889
29890
29891 static int
29892 left_overwritten (struct glyph_string *s)
29893 {
29894 int k;
29895
29896 if (s->left_overhang)
29897 {
29898 int x = 0, i;
29899 struct glyph *glyphs = s->row->glyphs[s->area];
29900 int first = s->first_glyph - glyphs;
29901
29902 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
29903 x -= glyphs[i].pixel_width;
29904
29905 k = i + 1;
29906 }
29907 else
29908 k = -1;
29909
29910 return k;
29911 }
29912
29913
29914
29915
29916
29917
29918 static int
29919 left_overwriting (struct glyph_string *s)
29920 {
29921 int i, k, x;
29922 struct glyph *glyphs = s->row->glyphs[s->area];
29923 int first = s->first_glyph - glyphs;
29924
29925 k = -1;
29926 x = 0;
29927 for (i = first - 1; i >= 0; --i)
29928 {
29929 int left, right;
29930 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
29931 if (x + right > 0)
29932 k = i;
29933 x -= glyphs[i].pixel_width;
29934 }
29935
29936 return k;
29937 }
29938
29939
29940
29941
29942
29943
29944 static int
29945 right_overwritten (struct glyph_string *s)
29946 {
29947 int k = -1;
29948
29949 if (s->right_overhang)
29950 {
29951 int x = 0, i;
29952 struct glyph *glyphs = s->row->glyphs[s->area];
29953 int first = (s->first_glyph - glyphs
29954 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
29955 int end = s->row->used[s->area];
29956
29957 for (i = first; i < end && s->right_overhang > x; ++i)
29958 x += glyphs[i].pixel_width;
29959
29960 k = i;
29961 }
29962
29963 return k;
29964 }
29965
29966
29967
29968
29969
29970
29971 static int
29972 right_overwriting (struct glyph_string *s)
29973 {
29974 int i, k, x;
29975 int end = s->row->used[s->area];
29976 struct glyph *glyphs = s->row->glyphs[s->area];
29977 int first = (s->first_glyph - glyphs
29978 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
29979
29980 k = -1;
29981 x = 0;
29982 for (i = first; i < end; ++i)
29983 {
29984 int left, right;
29985 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
29986 if (x - left < 0)
29987 k = i;
29988 x += glyphs[i].pixel_width;
29989 }
29990
29991 return k;
29992 }
29993
29994
29995
29996
29997
29998
29999
30000
30001
30002
30003
30004 static void
30005 set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
30006 {
30007
30008
30009
30010 if (start == s->row->used[s->area]
30011 && ((s->row->fill_line_p
30012 && (s->hl == DRAW_NORMAL_TEXT
30013 || s->hl == DRAW_IMAGE_RAISED
30014 || s->hl == DRAW_IMAGE_SUNKEN))
30015 || s->hl == DRAW_MOUSE_FACE))
30016 s->extends_to_end_of_line_p = true;
30017
30018
30019
30020
30021 if (s->extends_to_end_of_line_p)
30022 s->background_width = last_x - s->x + 1;
30023 else
30024 {
30025 s->background_width = s->width;
30026 #ifdef HAVE_WINDOW_SYSTEM
30027 if (FRAME_WINDOW_P (s->f)
30028 && s->hl == DRAW_CURSOR
30029 && MATRIX_ROW (s->w->current_matrix,
30030 s->w->phys_cursor.vpos)->mouse_face_p
30031 && cursor_in_mouse_face_p (s->w))
30032 {
30033
30034
30035
30036
30037 struct glyph *g = s->first_glyph;
30038 struct face *regular_face = FACE_FROM_ID (s->f, g->face_id);
30039 s->background_width +=
30040 adjust_glyph_width_for_mouse_face (g, s->row, s->w,
30041 regular_face, s->face);
30042
30043 s->width = s->background_width;
30044 }
30045 #endif
30046 }
30047 }
30048
30049
30050
30051
30052
30053 static struct glyph_string *
30054 glyph_string_containing_background_width (struct glyph_string *s)
30055 {
30056 if (s->cmp)
30057 while (s->cmp_from)
30058 s = s->prev;
30059
30060 return s;
30061 }
30062
30063
30064
30065
30066
30067
30068 static void
30069 compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
30070 {
30071 if (backward_p)
30072 {
30073 while (s)
30074 {
30075 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30076 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30077 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30078 x -= s->width;
30079 s->x = x;
30080 s = s->prev;
30081 }
30082 }
30083 else
30084 {
30085 while (s)
30086 {
30087 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30088 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30089 s->x = x;
30090 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30091 x += s->width;
30092 s = s->next;
30093 }
30094 }
30095 }
30096
30097
30098
30099
30100
30101
30102
30103
30104
30105 #ifdef HAVE_NTGUI
30106
30107
30108 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30109 init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
30110 #else
30111 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30112 init_glyph_string (s, char2b, w, row, area, start, hl)
30113 #endif
30114
30115
30116
30117
30118
30119
30120
30121
30122
30123
30124
30125 #define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30126 do \
30127 { \
30128 s = alloca (sizeof *s); \
30129 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30130 START = fill_stretch_glyph_string (s, START, END); \
30131 append_glyph_string (&HEAD, &TAIL, s); \
30132 s->x = (X); \
30133 } \
30134 while (false)
30135
30136
30137
30138
30139
30140
30141
30142
30143
30144
30145 #define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30146 do \
30147 { \
30148 s = alloca (sizeof *s); \
30149 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30150 fill_image_glyph_string (s); \
30151 append_glyph_string (&HEAD, &TAIL, s); \
30152 ++START; \
30153 s->x = (X); \
30154 } \
30155 while (false)
30156
30157 #ifndef HAVE_XWIDGETS
30158 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30159 eassume (false)
30160 #else
30161 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30162 do \
30163 { \
30164 s = alloca (sizeof *s); \
30165 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30166 fill_xwidget_glyph_string (s); \
30167 append_glyph_string (&(HEAD), &(TAIL), s); \
30168 ++(START); \
30169 s->x = (X); \
30170 } \
30171 while (false)
30172 #endif
30173
30174
30175
30176
30177
30178
30179
30180
30181
30182
30183 #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30184 do \
30185 { \
30186 int face_id; \
30187 unsigned *char2b; \
30188 \
30189 face_id = (row)->glyphs[area][START].face_id; \
30190 \
30191 s = alloca (sizeof *s); \
30192 SAFE_NALLOCA (char2b, 1, (END) - (START)); \
30193 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30194 append_glyph_string (&HEAD, &TAIL, s); \
30195 s->x = (X); \
30196 START = fill_glyph_string (s, face_id, START, END, overlaps); \
30197 } \
30198 while (false)
30199
30200
30201
30202
30203
30204
30205
30206
30207
30208
30209
30210 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30211 do { \
30212 int face_id = (row)->glyphs[area][START].face_id; \
30213 struct face *base_face = FACE_FROM_ID (f, face_id); \
30214 ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id; \
30215 struct composition *cmp = composition_table[cmp_id]; \
30216 unsigned *char2b; \
30217 struct glyph_string *first_s = NULL; \
30218 int n; \
30219 \
30220 SAFE_NALLOCA (char2b, 1, cmp->glyph_len); \
30221 \
30222
30223 \
30224 for (n = 0; n < cmp->glyph_len;) \
30225 { \
30226 s = alloca (sizeof *s); \
30227 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30228 append_glyph_string (&(HEAD), &(TAIL), s); \
30229 s->cmp = cmp; \
30230 s->cmp_from = n; \
30231 s->x = (X); \
30232 if (n == 0) \
30233 first_s = s; \
30234 n = fill_composite_glyph_string (s, base_face, overlaps); \
30235 } \
30236 \
30237 ++START; \
30238 s = first_s; \
30239 } while (false)
30240
30241
30242
30243
30244
30245 #define BUILD_GSTRING_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30246 do { \
30247 int face_id; \
30248 unsigned *char2b; \
30249 Lisp_Object gstring; \
30250 \
30251 face_id = (row)->glyphs[area][START].face_id; \
30252 gstring = (composition_gstring_from_id \
30253 ((row)->glyphs[area][START].u.cmp.id)); \
30254 s = alloca (sizeof *s); \
30255 SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring)); \
30256 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30257 append_glyph_string (&(HEAD), &(TAIL), s); \
30258 s->x = (X); \
30259 START = fill_gstring_glyph_string (s, face_id, START, END, overlaps); \
30260 } while (false)
30261
30262
30263
30264
30265
30266
30267 #define BUILD_GLYPHLESS_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30268 do \
30269 { \
30270 int face_id; \
30271 \
30272 face_id = (row)->glyphs[area][START].face_id; \
30273 \
30274 s = alloca (sizeof *s); \
30275 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30276 append_glyph_string (&HEAD, &TAIL, s); \
30277 s->x = (X); \
30278 START = fill_glyphless_glyph_string (s, face_id, START, END, \
30279 overlaps); \
30280 } \
30281 while (false)
30282
30283
30284
30285
30286
30287
30288
30289
30290
30291
30292
30293
30294 #define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30295 do \
30296 { \
30297 HEAD = TAIL = NULL; \
30298 while (START < END) \
30299 { \
30300 struct glyph *first_glyph = (row)->glyphs[area] + START; \
30301 switch (first_glyph->type) \
30302 { \
30303 case CHAR_GLYPH: \
30304 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \
30305 HL, X, LAST_X); \
30306 break; \
30307 \
30308 case COMPOSITE_GLYPH: \
30309 if (first_glyph->u.cmp.automatic) \
30310 BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \
30311 HL, X, LAST_X); \
30312 else \
30313 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \
30314 HL, X, LAST_X); \
30315 break; \
30316 \
30317 case STRETCH_GLYPH: \
30318 BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \
30319 HL, X, LAST_X); \
30320 break; \
30321 \
30322 case IMAGE_GLYPH: \
30323 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
30324 HL, X, LAST_X); \
30325 break;
30326
30327 #define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30328 case XWIDGET_GLYPH: \
30329 BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \
30330 HL, X, LAST_X); \
30331 break;
30332
30333 #define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \
30334 case GLYPHLESS_GLYPH: \
30335 BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \
30336 HL, X, LAST_X); \
30337 break; \
30338 \
30339 default: \
30340 emacs_abort (); \
30341 } \
30342 \
30343 if (s) \
30344 { \
30345 set_glyph_string_background_width (s, START, LAST_X); \
30346 (X) += s->width; \
30347 } \
30348 } \
30349 } while (false)
30350
30351
30352 #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30353 BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30354 BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30355 BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
30356
30357
30358
30359
30360
30361
30362
30363
30364
30365
30366
30367
30368
30369
30370
30371
30372
30373
30374
30375
30376
30377
30378
30379
30380 static int
30381 draw_glyphs (struct window *w, int x, struct glyph_row *row,
30382 enum glyph_row_area area, ptrdiff_t start, ptrdiff_t end,
30383 enum draw_glyphs_face hl, int overlaps)
30384 {
30385 struct glyph_string *head, *tail;
30386 struct glyph_string *s;
30387 struct glyph_string *clip_head = NULL, *clip_tail = NULL;
30388 int i, j, x_reached, last_x, area_left = 0;
30389 struct frame *f = XFRAME (WINDOW_FRAME (w));
30390
30391 ALLOCATE_HDC (hdc, f);
30392
30393
30394 end = min (end, row->used[area]);
30395 start = clip_to_bounds (0, start, end);
30396
30397
30398
30399 if (row->full_width_p)
30400 {
30401
30402
30403 area_left = WINDOW_LEFT_EDGE_X (w);
30404 last_x = (WINDOW_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w)
30405 - (row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
30406 }
30407 else
30408 {
30409 area_left = window_box_left (w, area);
30410 last_x = area_left + window_box_width (w, area);
30411 }
30412 x += area_left;
30413
30414
30415
30416
30417
30418 i = start;
30419 USE_SAFE_ALLOCA;
30420 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
30421 if (tail)
30422 {
30423 s = glyph_string_containing_background_width (tail);
30424 x_reached = s->x + s->background_width;
30425 }
30426 else
30427 x_reached = x;
30428
30429
30430
30431
30432 if (head && !overlaps && row->contains_overlapping_glyphs_p)
30433 {
30434 struct glyph_string *h, *t;
30435 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
30436 int mouse_beg_col UNINIT, mouse_end_col UNINIT;
30437 bool check_mouse_face = false;
30438 int dummy_x = 0;
30439
30440
30441
30442 if (area == TEXT_AREA && row->mouse_face_p
30443 && hlinfo->mouse_face_beg_row >= 0
30444 && hlinfo->mouse_face_end_row >= 0)
30445 {
30446 ptrdiff_t row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
30447
30448 if (row_vpos >= hlinfo->mouse_face_beg_row
30449 && row_vpos <= hlinfo->mouse_face_end_row)
30450 {
30451 check_mouse_face = true;
30452 mouse_beg_col = (row_vpos == hlinfo->mouse_face_beg_row)
30453 ? hlinfo->mouse_face_beg_col : 0;
30454 mouse_end_col = (row_vpos == hlinfo->mouse_face_end_row)
30455 ? hlinfo->mouse_face_end_col
30456 : row->used[TEXT_AREA];
30457 }
30458 }
30459
30460
30461 if (FRAME_RIF (f)->compute_glyph_string_overhangs)
30462 for (s = head; s; s = s->next)
30463 FRAME_RIF (f)->compute_glyph_string_overhangs (s);
30464
30465
30466
30467
30468
30469
30470 i = left_overwritten (head);
30471 if (i >= 0)
30472 {
30473 enum draw_glyphs_face overlap_hl;
30474
30475
30476
30477
30478
30479
30480
30481
30482 if (check_mouse_face
30483 && mouse_beg_col < start && mouse_end_col > i)
30484 overlap_hl = DRAW_MOUSE_FACE;
30485 else
30486 overlap_hl = DRAW_NORMAL_TEXT;
30487
30488 if (hl != overlap_hl)
30489 clip_head = head;
30490 j = i;
30491 BUILD_GLYPH_STRINGS (j, start, h, t,
30492 overlap_hl, dummy_x, last_x);
30493 start = i;
30494 compute_overhangs_and_x (t, head->x, true);
30495 prepend_glyph_string_lists (&head, &tail, h, t);
30496 if (clip_head == NULL)
30497 clip_head = head;
30498 }
30499
30500
30501
30502
30503
30504
30505
30506
30507 i = left_overwriting (head);
30508 if (i >= 0)
30509 {
30510 enum draw_glyphs_face overlap_hl;
30511
30512 if (check_mouse_face
30513 && mouse_beg_col < start && mouse_end_col > i)
30514 overlap_hl = DRAW_MOUSE_FACE;
30515 else
30516 overlap_hl = DRAW_NORMAL_TEXT;
30517
30518 if (hl == overlap_hl || clip_head == NULL)
30519 clip_head = head;
30520 BUILD_GLYPH_STRINGS (i, start, h, t,
30521 overlap_hl, dummy_x, last_x);
30522 for (s = h; s; s = s->next)
30523 s->background_filled_p = true;
30524 compute_overhangs_and_x (t, head->x, true);
30525 prepend_glyph_string_lists (&head, &tail, h, t);
30526 }
30527
30528
30529
30530
30531
30532 i = right_overwritten (tail);
30533 if (i >= 0)
30534 {
30535 enum draw_glyphs_face overlap_hl;
30536
30537 if (check_mouse_face
30538 && mouse_beg_col < i && mouse_end_col > end)
30539 overlap_hl = DRAW_MOUSE_FACE;
30540 else
30541 overlap_hl = DRAW_NORMAL_TEXT;
30542
30543 if (hl != overlap_hl)
30544 clip_tail = tail;
30545 BUILD_GLYPH_STRINGS (end, i, h, t,
30546 overlap_hl, x, last_x);
30547
30548
30549 compute_overhangs_and_x (h, tail->x + tail->width, false);
30550 append_glyph_string_lists (&head, &tail, h, t);
30551 if (clip_tail == NULL)
30552 clip_tail = tail;
30553 }
30554
30555
30556
30557
30558
30559
30560 i = right_overwriting (tail);
30561 if (i >= 0)
30562 {
30563 enum draw_glyphs_face overlap_hl;
30564 if (check_mouse_face
30565 && mouse_beg_col < i && mouse_end_col > end)
30566 overlap_hl = DRAW_MOUSE_FACE;
30567 else
30568 overlap_hl = DRAW_NORMAL_TEXT;
30569
30570 if (hl == overlap_hl || clip_tail == NULL)
30571 clip_tail = tail;
30572 i++;
30573 BUILD_GLYPH_STRINGS (end, i, h, t,
30574 overlap_hl, x, last_x);
30575 for (s = h; s; s = s->next)
30576 s->background_filled_p = true;
30577 compute_overhangs_and_x (h, tail->x + tail->width, false);
30578 append_glyph_string_lists (&head, &tail, h, t);
30579 }
30580 tail = glyph_string_containing_background_width (tail);
30581 if (clip_tail)
30582 clip_tail = glyph_string_containing_background_width (clip_tail);
30583 if (clip_head || clip_tail)
30584 for (s = head; s; s = s->next)
30585 {
30586 s->clip_head = clip_head;
30587 s->clip_tail = clip_tail;
30588 }
30589 }
30590
30591
30592 for (s = head; s; s = s->next)
30593 FRAME_RIF (f)->draw_glyph_string (s);
30594
30595
30596
30597 if (area == TEXT_AREA
30598 && !row->full_width_p
30599
30600
30601
30602 && !overlaps)
30603 {
30604 int x0 = clip_head ? clip_head->x : (head ? head->x : x);
30605 int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
30606 : (tail ? tail->x + tail->background_width : x));
30607 x0 -= area_left;
30608 x1 -= area_left;
30609
30610 notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
30611 row->y, MATRIX_ROW_BOTTOM_Y (row));
30612 }
30613
30614
30615
30616 if (row->full_width_p)
30617 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
30618 else
30619 x_reached -= area_left;
30620
30621 RELEASE_HDC (hdc, f);
30622
30623 SAFE_FREE ();
30624 return x_reached;
30625 }
30626
30627
30628
30629
30630
30631
30632
30633
30634 struct font *
30635 font_for_underline_metrics (struct glyph_string *s)
30636 {
30637 struct glyph *g0 = s->row->glyphs[s->area], *g;
30638
30639 for (g = s->first_glyph - 1; g >= g0; g--)
30640 {
30641 struct face *prev_face = FACE_FROM_ID (s->f, g->face_id);
30642 if (!(prev_face && prev_face->underline != FACE_NO_UNDERLINE))
30643 break;
30644 }
30645
30646
30647 if (g == s->first_glyph - 1)
30648 return s->font;
30649 else
30650 {
30651
30652
30653 return FACE_FROM_ID (s->f, g[1].face_id)->font;
30654 }
30655 }
30656
30657
30658
30659
30660 #define IT_EXPAND_MATRIX_WIDTH(it, area) \
30661 { \
30662 if (!it->f->fonts_changed \
30663 && (it->glyph_row->glyphs[area] \
30664 < it->glyph_row->glyphs[area + 1])) \
30665 { \
30666 it->w->ncols_scale_factor++; \
30667 it->f->fonts_changed = true; \
30668 } \
30669 }
30670
30671
30672
30673
30674 static void
30675 append_glyph (struct it *it)
30676 {
30677 struct glyph *glyph;
30678 enum glyph_row_area area = it->area;
30679
30680 eassert (it->glyph_row);
30681 eassert (it->char_to_display != '\n' && it->char_to_display != '\t');
30682
30683 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30684 if (glyph < it->glyph_row->glyphs[area + 1])
30685 {
30686
30687
30688 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30689 {
30690 struct glyph *g;
30691
30692
30693 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
30694 g[1] = *g;
30695 glyph = it->glyph_row->glyphs[area];
30696 }
30697 glyph->charpos = CHARPOS (it->position);
30698 glyph->object = it->object;
30699 if (it->pixel_width > 0)
30700 {
30701 eassert (it->pixel_width <= SHRT_MAX);
30702 glyph->pixel_width = it->pixel_width;
30703 glyph->padding_p = false;
30704 }
30705 else
30706 {
30707
30708
30709 glyph->pixel_width = 1;
30710 glyph->padding_p = true;
30711 }
30712 glyph->ascent = it->ascent;
30713 glyph->descent = it->descent;
30714 glyph->voffset = it->voffset;
30715 glyph->type = CHAR_GLYPH;
30716 glyph->avoid_cursor_p = it->avoid_cursor_p;
30717 glyph->multibyte_p = it->multibyte_p;
30718 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30719 {
30720
30721
30722 glyph->right_box_line_p = it->start_of_box_run_p;
30723 glyph->left_box_line_p = it->end_of_box_run_p;
30724 }
30725 else
30726 {
30727 glyph->left_box_line_p = it->start_of_box_run_p;
30728 glyph->right_box_line_p = it->end_of_box_run_p;
30729 }
30730 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
30731 || it->phys_descent > it->descent);
30732 glyph->glyph_not_available_p = it->glyph_not_available_p;
30733 glyph->face_id = it->face_id;
30734 glyph->u.ch = it->char_to_display;
30735 glyph->slice.img = null_glyph_slice;
30736 glyph->font_type = FONT_TYPE_UNKNOWN;
30737 if (it->bidi_p)
30738 {
30739 glyph->resolved_level = it->bidi_it.resolved_level;
30740 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
30741 glyph->bidi_type = it->bidi_it.type;
30742 }
30743 else
30744 {
30745 glyph->resolved_level = 0;
30746 glyph->bidi_type = UNKNOWN_BT;
30747 }
30748 ++it->glyph_row->used[area];
30749 }
30750 else
30751 IT_EXPAND_MATRIX_WIDTH (it, area);
30752 }
30753
30754
30755
30756
30757 static void
30758 append_composite_glyph (struct it *it)
30759 {
30760 struct glyph *glyph;
30761 enum glyph_row_area area = it->area;
30762
30763 eassert (it->glyph_row);
30764
30765 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30766 if (glyph < it->glyph_row->glyphs[area + 1])
30767 {
30768
30769
30770 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
30771 {
30772 struct glyph *g;
30773
30774
30775 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
30776 g[1] = *g;
30777 glyph = it->glyph_row->glyphs[it->area];
30778 }
30779 glyph->charpos = it->cmp_it.charpos;
30780 glyph->object = it->object;
30781 eassert (it->pixel_width <= SHRT_MAX);
30782 glyph->pixel_width = it->pixel_width;
30783 glyph->ascent = it->ascent;
30784 glyph->descent = it->descent;
30785 glyph->voffset = it->voffset;
30786 glyph->type = COMPOSITE_GLYPH;
30787 if (it->cmp_it.ch < 0)
30788 {
30789 glyph->u.cmp.automatic = false;
30790 glyph->u.cmp.id = it->cmp_it.id;
30791 glyph->slice.cmp.from = glyph->slice.cmp.to = 0;
30792 }
30793 else
30794 {
30795 glyph->u.cmp.automatic = true;
30796 glyph->u.cmp.id = it->cmp_it.id;
30797 glyph->slice.cmp.from = it->cmp_it.from;
30798 glyph->slice.cmp.to = it->cmp_it.to - 1;
30799 }
30800 glyph->avoid_cursor_p = it->avoid_cursor_p;
30801 glyph->multibyte_p = it->multibyte_p;
30802 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30803 {
30804
30805
30806 glyph->right_box_line_p = it->start_of_box_run_p;
30807 glyph->left_box_line_p = it->end_of_box_run_p;
30808 }
30809 else
30810 {
30811 glyph->left_box_line_p = it->start_of_box_run_p;
30812 glyph->right_box_line_p = it->end_of_box_run_p;
30813 }
30814 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
30815 || it->phys_descent > it->descent);
30816 glyph->padding_p = false;
30817 glyph->glyph_not_available_p = it->glyph_not_available_p;
30818 glyph->face_id = it->face_id;
30819 glyph->font_type = FONT_TYPE_UNKNOWN;
30820 if (it->bidi_p)
30821 {
30822 glyph->resolved_level = it->bidi_it.resolved_level;
30823 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
30824 glyph->bidi_type = it->bidi_it.type;
30825 }
30826 ++it->glyph_row->used[area];
30827 }
30828 else
30829 IT_EXPAND_MATRIX_WIDTH (it, area);
30830 }
30831
30832
30833
30834
30835
30836 static void
30837 take_vertical_position_into_account (struct it *it)
30838 {
30839 if (it->voffset)
30840 {
30841 if (it->voffset < 0)
30842
30843
30844 it->ascent -= it->voffset;
30845 else
30846
30847
30848 it->descent += it->voffset;
30849 }
30850 }
30851
30852
30853
30854
30855
30856
30857 static void
30858 produce_image_glyph (struct it *it)
30859 {
30860 struct image *img;
30861 struct face *face;
30862 int glyph_ascent, crop;
30863 struct glyph_slice slice;
30864
30865 eassert (it->what == IT_IMAGE);
30866
30867 face = FACE_FROM_ID (it->f, it->face_id);
30868
30869 prepare_face_for_display (it->f, face);
30870
30871 if (it->image_id < 0)
30872 {
30873
30874 it->ascent = it->phys_ascent = 0;
30875 it->descent = it->phys_descent = 0;
30876 it->pixel_width = 0;
30877 it->nglyphs = 0;
30878 return;
30879 }
30880
30881 img = IMAGE_FROM_ID (it->f, it->image_id);
30882
30883 prepare_image_for_display (it->f, img);
30884
30885 slice.x = slice.y = 0;
30886 slice.width = img->width;
30887 slice.height = img->height;
30888
30889 if (FIXNUMP (it->slice.x))
30890 slice.x = XFIXNUM (it->slice.x);
30891 else if (FLOATP (it->slice.x))
30892 slice.x = XFLOAT_DATA (it->slice.x) * img->width;
30893
30894 if (FIXNUMP (it->slice.y))
30895 slice.y = XFIXNUM (it->slice.y);
30896 else if (FLOATP (it->slice.y))
30897 slice.y = XFLOAT_DATA (it->slice.y) * img->height;
30898
30899 if (FIXNUMP (it->slice.width))
30900 slice.width = XFIXNUM (it->slice.width);
30901 else if (FLOATP (it->slice.width))
30902 slice.width = XFLOAT_DATA (it->slice.width) * img->width;
30903
30904 if (FIXNUMP (it->slice.height))
30905 slice.height = XFIXNUM (it->slice.height);
30906 else if (FLOATP (it->slice.height))
30907 slice.height = XFLOAT_DATA (it->slice.height) * img->height;
30908
30909 if (slice.x >= img->width)
30910 slice.x = img->width;
30911 if (slice.y >= img->height)
30912 slice.y = img->height;
30913 if (slice.x + slice.width >= img->width)
30914 slice.width = img->width - slice.x;
30915 if (slice.y + slice.height > img->height)
30916 slice.height = img->height - slice.y;
30917
30918 if (slice.width == 0 || slice.height == 0)
30919 return;
30920
30921 it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face, &slice);
30922
30923 it->descent = slice.height - glyph_ascent;
30924 if (slice.y == 0)
30925 it->descent += img->vmargin;
30926 if (slice.y + slice.height == img->height)
30927 it->descent += img->vmargin;
30928 it->phys_descent = it->descent;
30929
30930 it->pixel_width = slice.width;
30931 if (slice.x == 0)
30932 it->pixel_width += img->hmargin;
30933 if (slice.x + slice.width == img->width)
30934 it->pixel_width += img->hmargin;
30935
30936
30937
30938 if (it->descent < 0)
30939 it->descent = 0;
30940
30941 it->nglyphs = 1;
30942
30943 if (face->box != FACE_NO_BOX)
30944 {
30945
30946
30947 if (face->box_horizontal_line_width > 0)
30948 {
30949 if (slice.y == 0)
30950 it->ascent += face->box_horizontal_line_width;
30951 if (slice.y + slice.height == img->height)
30952 it->descent += face->box_horizontal_line_width;
30953 }
30954
30955 if (face->box_vertical_line_width > 0)
30956 {
30957 if (it->start_of_box_run_p && slice.x == 0)
30958 it->pixel_width += face->box_vertical_line_width;
30959 if (it->end_of_box_run_p && slice.x + slice.width == img->width)
30960 it->pixel_width += face->box_vertical_line_width;
30961 }
30962 }
30963
30964 take_vertical_position_into_account (it);
30965
30966
30967
30968 if ((crop = it->pixel_width - (it->last_visible_x - it->current_x), crop > 0)
30969 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
30970 {
30971 it->pixel_width -= crop;
30972 slice.width -= crop;
30973 }
30974
30975 if (it->glyph_row)
30976 {
30977 struct glyph *glyph;
30978 enum glyph_row_area area = it->area;
30979
30980 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30981 if (it->glyph_row->reversed_p)
30982 {
30983 struct glyph *g;
30984
30985
30986 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
30987 g[1] = *g;
30988 glyph = it->glyph_row->glyphs[it->area];
30989 }
30990 if (glyph < it->glyph_row->glyphs[area + 1])
30991 {
30992 glyph->charpos = CHARPOS (it->position);
30993 glyph->object = it->object;
30994 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
30995 glyph->ascent = glyph_ascent;
30996 glyph->descent = it->descent;
30997 glyph->voffset = it->voffset;
30998 glyph->type = IMAGE_GLYPH;
30999 glyph->avoid_cursor_p = it->avoid_cursor_p;
31000 glyph->multibyte_p = it->multibyte_p;
31001 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31002 {
31003
31004
31005 glyph->right_box_line_p = it->start_of_box_run_p;
31006 glyph->left_box_line_p = it->end_of_box_run_p;
31007 }
31008 else
31009 {
31010 glyph->left_box_line_p = it->start_of_box_run_p;
31011 glyph->right_box_line_p = it->end_of_box_run_p;
31012 }
31013 glyph->overlaps_vertically_p = false;
31014 glyph->padding_p = false;
31015 glyph->glyph_not_available_p = false;
31016 glyph->face_id = it->face_id;
31017 glyph->u.img_id = img->id;
31018 glyph->slice.img = slice;
31019 glyph->font_type = FONT_TYPE_UNKNOWN;
31020 if (it->bidi_p)
31021 {
31022 glyph->resolved_level = it->bidi_it.resolved_level;
31023 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31024 glyph->bidi_type = it->bidi_it.type;
31025 }
31026 ++it->glyph_row->used[area];
31027 }
31028 else
31029 IT_EXPAND_MATRIX_WIDTH (it, area);
31030 }
31031 }
31032
31033 static void
31034 produce_xwidget_glyph (struct it *it)
31035 {
31036 #ifdef HAVE_XWIDGETS
31037 struct xwidget *xw;
31038 int glyph_ascent, crop;
31039 eassert (it->what == IT_XWIDGET);
31040
31041 struct face *face = FACE_FROM_ID (it->f, it->face_id);
31042
31043 prepare_face_for_display (it->f, face);
31044
31045 xw = it->xwidget;
31046 it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;
31047 it->descent = xw->height/2;
31048 it->phys_descent = it->descent;
31049 it->pixel_width = xw->width;
31050
31051
31052 if (it->descent < 0)
31053 it->descent = 0;
31054
31055 it->nglyphs = 1;
31056
31057 if (face->box != FACE_NO_BOX)
31058 {
31059 if (face->box_horizontal_line_width > 0)
31060 {
31061 it->ascent += face->box_horizontal_line_width;
31062 it->descent += face->box_horizontal_line_width;
31063 }
31064
31065 if (face->box_vertical_line_width > 0)
31066 {
31067 if (it->start_of_box_run_p)
31068 it->pixel_width += face->box_vertical_line_width;
31069 it->pixel_width += face->box_vertical_line_width;
31070 }
31071 }
31072
31073 take_vertical_position_into_account (it);
31074
31075
31076
31077 crop = it->pixel_width - (it->last_visible_x - it->current_x);
31078 if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31079 it->pixel_width -= crop;
31080
31081 if (it->glyph_row)
31082 {
31083 enum glyph_row_area area = it->area;
31084 struct glyph *glyph
31085 = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31086
31087 if (it->glyph_row->reversed_p)
31088 {
31089 struct glyph *g;
31090
31091
31092 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31093 g[1] = *g;
31094 glyph = it->glyph_row->glyphs[it->area];
31095 }
31096 if (glyph < it->glyph_row->glyphs[area + 1])
31097 {
31098 glyph->charpos = CHARPOS (it->position);
31099 glyph->object = it->object;
31100 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31101 glyph->ascent = glyph_ascent;
31102 glyph->descent = it->descent;
31103 glyph->voffset = it->voffset;
31104 glyph->type = XWIDGET_GLYPH;
31105 glyph->avoid_cursor_p = it->avoid_cursor_p;
31106 glyph->multibyte_p = it->multibyte_p;
31107 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31108 {
31109
31110
31111 glyph->right_box_line_p = it->start_of_box_run_p;
31112 glyph->left_box_line_p = it->end_of_box_run_p;
31113 }
31114 else
31115 {
31116 glyph->left_box_line_p = it->start_of_box_run_p;
31117 glyph->right_box_line_p = it->end_of_box_run_p;
31118 }
31119 glyph->overlaps_vertically_p = 0;
31120 glyph->padding_p = 0;
31121 glyph->glyph_not_available_p = 0;
31122 glyph->face_id = it->face_id;
31123 glyph->u.xwidget = it->xwidget->xwidget_id;
31124 glyph->font_type = FONT_TYPE_UNKNOWN;
31125 if (it->bidi_p)
31126 {
31127 glyph->resolved_level = it->bidi_it.resolved_level;
31128 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31129 glyph->bidi_type = it->bidi_it.type;
31130 }
31131 ++it->glyph_row->used[area];
31132 }
31133 else
31134 IT_EXPAND_MATRIX_WIDTH (it, area);
31135 }
31136 #endif
31137 }
31138
31139
31140
31141
31142
31143 static void
31144 append_stretch_glyph (struct it *it, Lisp_Object object,
31145 int width, int height, int ascent)
31146 {
31147 struct glyph *glyph;
31148 enum glyph_row_area area = it->area;
31149
31150 eassert (ascent >= 0 && ascent <= height);
31151
31152 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31153 if (glyph < it->glyph_row->glyphs[area + 1])
31154 {
31155
31156
31157 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31158 {
31159 struct glyph *g;
31160
31161
31162 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31163 g[1] = *g;
31164 glyph = it->glyph_row->glyphs[area];
31165
31166
31167
31168
31169
31170
31171
31172
31173
31174
31175
31176
31177
31178
31179
31180 if (it->current_x < it->first_visible_x)
31181 width -= it->first_visible_x - it->current_x;
31182 eassert (width > 0);
31183 }
31184 glyph->charpos = CHARPOS (it->position);
31185 glyph->object = object;
31186
31187
31188 glyph->pixel_width = clip_to_bounds (-1, width, SHRT_MAX);
31189 glyph->ascent = ascent;
31190 glyph->descent = height - ascent;
31191 glyph->voffset = it->voffset;
31192 glyph->type = STRETCH_GLYPH;
31193 glyph->avoid_cursor_p = it->avoid_cursor_p;
31194 glyph->multibyte_p = it->multibyte_p;
31195 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31196 {
31197
31198
31199 glyph->right_box_line_p = it->start_of_box_run_p;
31200 glyph->left_box_line_p = it->end_of_box_run_p;
31201 }
31202 else
31203 {
31204 glyph->left_box_line_p = it->start_of_box_run_p;
31205 glyph->right_box_line_p = it->end_of_box_run_p;
31206 }
31207 glyph->overlaps_vertically_p = false;
31208 glyph->padding_p = false;
31209 glyph->glyph_not_available_p = false;
31210 glyph->face_id = it->face_id;
31211 glyph->u.stretch.ascent = ascent;
31212 glyph->u.stretch.height = height;
31213 glyph->slice.img = null_glyph_slice;
31214 glyph->font_type = FONT_TYPE_UNKNOWN;
31215 if (it->bidi_p)
31216 {
31217 glyph->resolved_level = it->bidi_it.resolved_level;
31218 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31219 glyph->bidi_type = it->bidi_it.type;
31220 }
31221 else
31222 {
31223 glyph->resolved_level = 0;
31224 glyph->bidi_type = UNKNOWN_BT;
31225 }
31226 ++it->glyph_row->used[area];
31227 }
31228 else
31229 IT_EXPAND_MATRIX_WIDTH (it, area);
31230 }
31231
31232 #endif
31233
31234
31235
31236
31237
31238
31239
31240
31241
31242
31243
31244
31245
31246
31247
31248
31249
31250
31251
31252
31253
31254
31255
31256
31257
31258
31259
31260
31261
31262
31263
31264
31265 void
31266 produce_stretch_glyph (struct it *it)
31267 {
31268
31269 Lisp_Object prop, plist;
31270 int width = 0, height = 0, align_to = -1;
31271 bool zero_width_ok_p = false;
31272 double tem;
31273 struct font *font = NULL;
31274
31275 #ifdef HAVE_WINDOW_SYSTEM
31276 int ascent = 0;
31277 bool zero_height_ok_p = false;
31278 struct face *face = NULL;
31279
31280 if (FRAME_WINDOW_P (it->f))
31281 {
31282 face = FACE_FROM_ID (it->f, it->face_id);
31283 font = face->font ? face->font : FRAME_FONT (it->f);
31284 prepare_face_for_display (it->f, face);
31285 }
31286 #endif
31287
31288
31289 eassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
31290 plist = XCDR (it->object);
31291
31292
31293 if ((prop = plist_get (plist, QCwidth), !NILP (prop))
31294 && calc_pixel_width_or_height (&tem, it, prop, font, true, NULL))
31295 {
31296
31297 zero_width_ok_p = true;
31298 width = (int)tem;
31299 }
31300 else if (prop = plist_get (plist, QCrelative_width), NUMVAL (prop) > 0)
31301 {
31302
31303
31304
31305 struct it it2;
31306 Lisp_Object object =
31307 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31308 unsigned char *p = (STRINGP (object)
31309 ? SDATA (object) + IT_STRING_BYTEPOS (*it)
31310 : BYTE_POS_ADDR (IT_BYTEPOS (*it)));
31311 bool multibyte_p =
31312 STRINGP (object) ? STRING_MULTIBYTE (object) : it->multibyte_p;
31313
31314 it2 = *it;
31315 if (multibyte_p)
31316 {
31317 it2.c = it2.char_to_display = string_char_and_length (p, &it2.len);
31318 #ifdef HAVE_WINDOW_SYSTEM
31319 if (FRAME_WINDOW_P (it->f) && ! ASCII_CHAR_P (it2.c))
31320 it2.face_id = FACE_FOR_CHAR (it->f, face, it2.c,
31321 IT_CHARPOS (*it),
31322 STRINGP (object)? object : Qnil);
31323 #endif
31324 }
31325 else
31326 {
31327 it2.c = it2.char_to_display = *p, it2.len = 1;
31328 if (! ASCII_CHAR_P (it2.c))
31329 it2.char_to_display = BYTE8_TO_CHAR (it2.c);
31330 }
31331
31332 it2.glyph_row = NULL;
31333 it2.what = IT_CHARACTER;
31334 PRODUCE_GLYPHS (&it2);
31335 width = NUMVAL (prop) * it2.pixel_width;
31336 }
31337 else if ((prop = plist_get (plist, QCalign_to), !NILP (prop))
31338 && calc_pixel_width_or_height (&tem, it, prop, font, true,
31339 &align_to))
31340 {
31341 int x = it->current_x + it->continuation_lines_width;
31342 int x0 = x;
31343
31344 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31345 {
31346 x -= it->lnum_pixel_width;
31347
31348 if (x + it->stretch_adjust >= it->first_visible_x)
31349 x += it->stretch_adjust;
31350 }
31351
31352 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
31353 align_to = (align_to < 0
31354 ? 0
31355 : align_to - window_box_left_offset (it->w, TEXT_AREA));
31356 else if (align_to < 0)
31357 align_to = window_box_left_offset (it->w, TEXT_AREA);
31358 width = max (0, (int)tem + align_to - x);
31359
31360 int next_x = x + width;
31361 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31362 {
31363
31364
31365 if (x < it->first_visible_x)
31366 {
31367 next_x -= it->first_visible_x - x;
31368 it->stretch_adjust = it->first_visible_x - x;
31369 }
31370 else
31371 next_x -= it->stretch_adjust;
31372 }
31373 width = next_x - x0;
31374 zero_width_ok_p = true;
31375 }
31376 else
31377
31378 width = FRAME_COLUMN_WIDTH (it->f);
31379
31380 if (width <= 0 && (width < 0 || !zero_width_ok_p))
31381 width = 1;
31382
31383 #ifdef HAVE_WINDOW_SYSTEM
31384
31385 if (FRAME_WINDOW_P (it->f))
31386 {
31387 int default_height = normal_char_height (font, ' ');
31388
31389 if ((prop = plist_get (plist, QCheight), !NILP (prop))
31390 && calc_pixel_width_or_height (&tem, it, prop, font, false, NULL))
31391 {
31392 height = (int)tem;
31393 zero_height_ok_p = true;
31394 }
31395 else if (prop = plist_get (plist, QCrelative_height),
31396 NUMVAL (prop) > 0)
31397 height = default_height * NUMVAL (prop);
31398 else
31399 height = default_height;
31400
31401 if (height <= 0 && (height < 0 || !zero_height_ok_p))
31402 height = 1;
31403
31404
31405
31406
31407 if (prop = plist_get (plist, QCascent),
31408 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
31409 ascent = height * NUMVAL (prop) / 100.0;
31410 else if (!NILP (prop)
31411 && calc_pixel_width_or_height (&tem, it, prop, font, false, 0))
31412 ascent = min (max (0, (int)tem), height);
31413 else
31414 ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
31415 }
31416 else
31417 #endif
31418 height = 1;
31419
31420 if (width > 0
31421 && it->area == TEXT_AREA && it->line_wrap != TRUNCATE
31422 && it->current_x + width > it->last_visible_x)
31423 {
31424 width = it->last_visible_x - it->current_x;
31425 #ifdef HAVE_WINDOW_SYSTEM
31426
31427
31428 width -= FRAME_WINDOW_P (it->f);
31429 #endif
31430 }
31431
31432 if (width > 0 && height > 0 && it->glyph_row)
31433 {
31434 Lisp_Object o_object = it->object;
31435 Lisp_Object object =
31436 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31437 int n = width;
31438
31439 if (!STRINGP (object))
31440 object = it->w->contents;
31441 #ifdef HAVE_WINDOW_SYSTEM
31442 if (FRAME_WINDOW_P (it->f))
31443 append_stretch_glyph (it, object, width, height, ascent);
31444 else
31445 #endif
31446 {
31447 it->object = object;
31448 it->char_to_display = ' ';
31449 it->pixel_width = it->len = 1;
31450 while (n--)
31451 tty_append_glyph (it);
31452 it->object = o_object;
31453 }
31454 }
31455
31456 it->pixel_width = width;
31457 #ifdef HAVE_WINDOW_SYSTEM
31458 if (FRAME_WINDOW_P (it->f))
31459 {
31460 it->ascent = it->phys_ascent = ascent;
31461 it->descent = it->phys_descent = height - it->ascent;
31462 it->nglyphs = width > 0 && height > 0;
31463 take_vertical_position_into_account (it);
31464 }
31465 else
31466 #endif
31467 it->nglyphs = width;
31468 }
31469
31470
31471
31472
31473
31474
31475
31476 static void
31477 produce_special_glyphs (struct it *it, enum display_element_type what)
31478 {
31479 struct it temp_it;
31480 Lisp_Object gc;
31481 GLYPH glyph;
31482
31483 temp_it = *it;
31484 temp_it.object = Qnil;
31485 memset (&temp_it.current, 0, sizeof temp_it.current);
31486
31487 if (what == IT_CONTINUATION)
31488 {
31489
31490 if (it->bidi_it.paragraph_dir == R2L)
31491 SET_GLYPH_FROM_CHAR (glyph, '/');
31492 else
31493 SET_GLYPH_FROM_CHAR (glyph, '\\');
31494 if (it->dp
31495 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31496 {
31497
31498 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31499 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31500 }
31501 }
31502 else if (what == IT_TRUNCATION)
31503 {
31504
31505 SET_GLYPH_FROM_CHAR (glyph, '$');
31506 if (it->dp
31507 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31508 {
31509
31510 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31511 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31512 }
31513 }
31514 else
31515 emacs_abort ();
31516
31517 #ifdef HAVE_WINDOW_SYSTEM
31518
31519
31520
31521
31522
31523 if (FRAME_WINDOW_P (temp_it.f)
31524
31525
31526
31527 && temp_it.glyph_row
31528
31529
31530
31531 && temp_it.glyph_row->used[TEXT_AREA] > 0
31532 && (temp_it.glyph_row->reversed_p
31533 ? WINDOW_LEFT_FRINGE_WIDTH (temp_it.w)
31534 : WINDOW_RIGHT_FRINGE_WIDTH (temp_it.w)) == 0)
31535 {
31536 int stretch_width = temp_it.last_visible_x - temp_it.current_x;
31537
31538 if (stretch_width > 0)
31539 {
31540 struct face *face = FACE_FROM_ID (temp_it.f, temp_it.face_id);
31541 struct font *font =
31542 face->font ? face->font : FRAME_FONT (temp_it.f);
31543 int stretch_ascent =
31544 (((temp_it.ascent + temp_it.descent)
31545 * FONT_BASE (font)) / FONT_HEIGHT (font));
31546
31547 append_stretch_glyph (&temp_it, Qnil, stretch_width,
31548 temp_it.ascent + temp_it.descent,
31549 stretch_ascent);
31550 }
31551 }
31552 #endif
31553
31554 temp_it.dp = NULL;
31555 temp_it.what = IT_CHARACTER;
31556 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31557 temp_it.face_id = GLYPH_FACE (glyph);
31558 temp_it.len = CHAR_BYTES (temp_it.c);
31559
31560 PRODUCE_GLYPHS (&temp_it);
31561 it->pixel_width = temp_it.pixel_width;
31562 it->nglyphs = temp_it.nglyphs;
31563 }
31564
31565 #ifdef HAVE_WINDOW_SYSTEM
31566
31567
31568
31569
31570
31571
31572
31573
31574
31575 static Lisp_Object
31576 calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
31577 int boff, bool override)
31578 {
31579 Lisp_Object face_name = Qnil;
31580 int ascent, descent, height;
31581
31582 if (NILP (val) || INTEGERP (val) || (override && EQ (val, Qt)))
31583 return val;
31584
31585 if (CONSP (val))
31586 {
31587 face_name = XCAR (val);
31588 val = XCDR (val);
31589 if (!NUMBERP (val))
31590 val = make_fixnum (1);
31591 if (NILP (face_name))
31592 {
31593 height = it->ascent + it->descent;
31594 goto scale;
31595 }
31596 }
31597
31598 if (NILP (face_name))
31599 {
31600 font = FRAME_FONT (it->f);
31601 boff = FRAME_BASELINE_OFFSET (it->f);
31602 }
31603 else if (EQ (face_name, Qt))
31604 {
31605 override = false;
31606 }
31607 else
31608 {
31609 int face_id;
31610 struct face *face;
31611
31612 face_id = lookup_named_face (it->w, it->f, face_name, false);
31613 face = FACE_FROM_ID_OR_NULL (it->f, face_id);
31614 if (face == NULL || ((font = face->font) == NULL))
31615 return make_fixnum (-1);
31616 boff = font->baseline_offset;
31617 if (font->vertical_centering)
31618 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
31619 }
31620
31621 normal_char_ascent_descent (font, -1, &ascent, &descent);
31622
31623 if (override)
31624 {
31625 it->override_ascent = ascent;
31626 it->override_descent = descent;
31627 it->override_boff = boff;
31628 }
31629
31630 height = ascent + descent;
31631
31632 scale:
31633
31634 if (FLOATP (val))
31635 height = (int)(XFLOAT_DATA (val) * height);
31636 else if (INTEGERP (val))
31637 {
31638 intmax_t v;
31639 if (integer_to_intmax (val, &v))
31640 height *= v;
31641 }
31642
31643 return make_fixnum (height);
31644 }
31645
31646
31647
31648
31649
31650
31651
31652
31653
31654
31655
31656
31657
31658
31659 static void
31660 append_glyphless_glyph (struct it *it, int face_id, bool for_no_font, int len,
31661 short upper_xoff, short upper_yoff,
31662 short lower_xoff, short lower_yoff)
31663 {
31664 struct glyph *glyph;
31665 enum glyph_row_area area = it->area;
31666
31667 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31668 if (glyph < it->glyph_row->glyphs[area + 1])
31669 {
31670
31671
31672 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31673 {
31674 struct glyph *g;
31675
31676
31677 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31678 g[1] = *g;
31679 glyph = it->glyph_row->glyphs[area];
31680 }
31681 glyph->charpos = CHARPOS (it->position);
31682 glyph->object = it->object;
31683 eassert (it->pixel_width <= SHRT_MAX);
31684 glyph->pixel_width = it->pixel_width;
31685 glyph->ascent = it->ascent;
31686 glyph->descent = it->descent;
31687 glyph->voffset = it->voffset;
31688 glyph->type = GLYPHLESS_GLYPH;
31689 glyph->u.glyphless.method = it->glyphless_method;
31690 glyph->u.glyphless.for_no_font = for_no_font;
31691 glyph->u.glyphless.len = len;
31692 glyph->u.glyphless.ch = it->c;
31693 glyph->slice.glyphless.upper_xoff = upper_xoff;
31694 glyph->slice.glyphless.upper_yoff = upper_yoff;
31695 glyph->slice.glyphless.lower_xoff = lower_xoff;
31696 glyph->slice.glyphless.lower_yoff = lower_yoff;
31697 glyph->avoid_cursor_p = it->avoid_cursor_p;
31698 glyph->multibyte_p = it->multibyte_p;
31699 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31700 {
31701
31702
31703 glyph->right_box_line_p = it->start_of_box_run_p;
31704 glyph->left_box_line_p = it->end_of_box_run_p;
31705 }
31706 else
31707 {
31708 glyph->left_box_line_p = it->start_of_box_run_p;
31709 glyph->right_box_line_p = it->end_of_box_run_p;
31710 }
31711 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31712 || it->phys_descent > it->descent);
31713 glyph->padding_p = false;
31714 glyph->glyph_not_available_p = false;
31715 glyph->face_id = face_id;
31716 glyph->font_type = FONT_TYPE_UNKNOWN;
31717 if (it->bidi_p)
31718 {
31719 glyph->resolved_level = it->bidi_it.resolved_level;
31720 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31721 glyph->bidi_type = it->bidi_it.type;
31722 }
31723 ++it->glyph_row->used[area];
31724 }
31725 else
31726 IT_EXPAND_MATRIX_WIDTH (it, area);
31727 }
31728
31729
31730
31731
31732
31733
31734
31735
31736
31737
31738
31739 static void
31740 produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
31741 {
31742 int face_id;
31743 struct face *face;
31744 struct font *font;
31745 int base_width, base_height, width, height;
31746 short upper_xoff, upper_yoff, lower_xoff, lower_yoff;
31747 int len;
31748
31749
31750
31751 face = FACE_FROM_ID (it->f, it->face_id)->ascii_face;
31752 font = face->font ? face->font : FRAME_FONT (it->f);
31753 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
31754 it->ascent += font->baseline_offset;
31755 it->descent -= font->baseline_offset;
31756 base_height = it->ascent + it->descent;
31757 base_width = font->average_width;
31758
31759 face_id = merge_glyphless_glyph_face (it);
31760
31761 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
31762 {
31763 it->pixel_width = THIN_SPACE_WIDTH;
31764 len = 0;
31765 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
31766 }
31767 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
31768 {
31769 width = CHARACTER_WIDTH (it->c);
31770 if (width == 0)
31771 width = 1;
31772 else if (width > 4)
31773 width = 4;
31774 it->pixel_width = base_width * width;
31775 len = 0;
31776 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
31777 }
31778 else
31779 {
31780 char buf[7];
31781 const char *str;
31782 unsigned int code[6];
31783 int upper_len;
31784 int ascent, descent;
31785 struct font_metrics metrics_upper, metrics_lower;
31786
31787 face = FACE_FROM_ID (it->f, face_id);
31788 font = face->font ? face->font : FRAME_FONT (it->f);
31789 prepare_face_for_display (it->f, face);
31790
31791 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
31792 {
31793 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
31794 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
31795 if (CONSP (acronym))
31796 acronym = XCAR (acronym);
31797 str = STRINGP (acronym) ? SSDATA (acronym) : "";
31798 }
31799 else
31800 {
31801 eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
31802 sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c + 0u);
31803 str = buf;
31804 }
31805 for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
31806 code[len] = font->driver->encode_char (font, str[len]);
31807 upper_len = (len + 1) / 2;
31808 font->driver->text_extents (font, code, upper_len,
31809 &metrics_upper);
31810 font->driver->text_extents (font, code + upper_len, len - upper_len,
31811 &metrics_lower);
31812
31813
31814
31815
31816 width = max (metrics_upper.width, metrics_lower.width) + 4;
31817 upper_xoff = lower_xoff = 2;
31818 if (base_width >= width)
31819 {
31820
31821 it->pixel_width = base_width;
31822 lower_xoff = base_width - 2 - metrics_lower.width;
31823 }
31824 else
31825 {
31826
31827 it->pixel_width = width;
31828 if (metrics_upper.width >= metrics_lower.width)
31829 lower_xoff = (width - metrics_lower.width) / 2;
31830 else
31831 upper_xoff = (width - metrics_upper.width) / 2;
31832 }
31833
31834
31835
31836 height = (metrics_upper.ascent + metrics_upper.descent
31837 + metrics_lower.ascent + metrics_lower.descent) + 5;
31838
31839
31840
31841
31842
31843
31844
31845
31846 ascent = - (it->descent - (base_height + height + 1) / 2);
31847 descent = it->descent - (base_height - height) / 2;
31848 lower_yoff = descent - 2 - metrics_lower.descent;
31849 upper_yoff = (lower_yoff - metrics_lower.ascent - 1
31850 - metrics_upper.descent);
31851
31852 if (height > base_height)
31853 {
31854 it->ascent = ascent;
31855 it->descent = descent;
31856 }
31857 }
31858
31859 it->phys_ascent = it->ascent;
31860 it->phys_descent = it->descent;
31861 if (it->glyph_row)
31862 append_glyphless_glyph (it, face_id, for_no_font, len,
31863 upper_xoff, upper_yoff,
31864 lower_xoff, lower_yoff);
31865 it->nglyphs = 1;
31866 take_vertical_position_into_account (it);
31867 }
31868
31869
31870
31871
31872
31873 #define IT_APPLY_FACE_BOX(it, face) \
31874 do { \
31875 if (face->box != FACE_NO_BOX) \
31876 { \
31877 int thick = face->box_horizontal_line_width; \
31878 if (thick > 0) \
31879 { \
31880 it->ascent += thick; \
31881 it->descent += thick; \
31882 } \
31883 \
31884 thick = face->box_vertical_line_width; \
31885 if (thick > 0) \
31886 { \
31887 if (it->start_of_box_run_p) \
31888 it->pixel_width += thick; \
31889 if (it->end_of_box_run_p) \
31890 it->pixel_width += thick; \
31891 } \
31892 } \
31893 } while (false)
31894
31895
31896
31897
31898
31899
31900 void
31901 gui_produce_glyphs (struct it *it)
31902 {
31903 int extra_line_spacing = it->extra_line_spacing;
31904
31905 it->glyph_not_available_p = false;
31906
31907 if (it->what == IT_CHARACTER)
31908 {
31909 unsigned char2b;
31910 struct face *face = FACE_FROM_ID (it->f, it->face_id);
31911 struct font *font = face->font;
31912 struct font_metrics *pcm = NULL;
31913 int boff;
31914
31915 if (font == NULL)
31916 {
31917
31918
31919
31920 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
31921
31922 eassert (it->what == IT_GLYPHLESS);
31923 produce_glyphless_glyph (it, true,
31924 STRINGP (acronym) ? acronym : Qnil);
31925 goto done;
31926 }
31927
31928 boff = font->baseline_offset;
31929 if (font->vertical_centering)
31930 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
31931
31932 if (it->char_to_display != '\n' && it->char_to_display != '\t')
31933 {
31934 it->nglyphs = 1;
31935
31936 if (it->override_ascent >= 0)
31937 {
31938 it->ascent = it->override_ascent;
31939 it->descent = it->override_descent;
31940 boff = it->override_boff;
31941 }
31942 else
31943 {
31944 it->ascent = FONT_BASE (font) + boff;
31945 it->descent = FONT_DESCENT (font) - boff;
31946 }
31947
31948 if (get_char_glyph_code (it->char_to_display, font, &char2b))
31949 {
31950 pcm = get_per_char_metric (font, &char2b);
31951 if (pcm->width == 0
31952 && pcm->rbearing == 0 && pcm->lbearing == 0)
31953 pcm = NULL;
31954 }
31955
31956 if (pcm)
31957 {
31958 it->phys_ascent = pcm->ascent + boff;
31959 it->phys_descent = pcm->descent - boff;
31960 it->pixel_width = pcm->width;
31961
31962
31963 if (it->override_ascent < 0)
31964 {
31965 if (FONT_TOO_HIGH (font))
31966 {
31967 it->ascent = it->phys_ascent;
31968 it->descent = it->phys_descent;
31969
31970
31971 if (it->ascent < 0)
31972 it->ascent = 0;
31973 if (it->descent < 0)
31974 it->descent = 0;
31975 }
31976 }
31977 }
31978 else
31979 {
31980 it->glyph_not_available_p = true;
31981 it->phys_ascent = it->ascent;
31982 it->phys_descent = it->descent;
31983 it->pixel_width = font->space_width;
31984 }
31985
31986 if (it->constrain_row_ascent_descent_p)
31987 {
31988 if (it->descent > it->max_descent)
31989 {
31990 it->ascent += it->descent - it->max_descent;
31991 it->descent = it->max_descent;
31992 }
31993 if (it->ascent > it->max_ascent)
31994 {
31995 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
31996 it->ascent = it->max_ascent;
31997 }
31998 it->phys_ascent = min (it->phys_ascent, it->ascent);
31999 it->phys_descent = min (it->phys_descent, it->descent);
32000 extra_line_spacing = 0;
32001 }
32002
32003
32004
32005 bool stretched_p
32006 = it->char_to_display == ' ' && !NILP (it->space_width);
32007 if (stretched_p)
32008 it->pixel_width *= XFLOATINT (it->space_width);
32009
32010 IT_APPLY_FACE_BOX(it, face);
32011
32012
32013
32014 if (face->overline_p)
32015 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32016
32017 if (it->constrain_row_ascent_descent_p)
32018 {
32019 if (it->ascent > it->max_ascent)
32020 it->ascent = it->max_ascent;
32021 if (it->descent > it->max_descent)
32022 it->descent = it->max_descent;
32023 }
32024
32025 take_vertical_position_into_account (it);
32026
32027
32028 if (it->glyph_row)
32029 {
32030 if (stretched_p)
32031 {
32032
32033
32034 int ascent = (((it->ascent + it->descent) * FONT_BASE (font))
32035 / FONT_HEIGHT (font));
32036 append_stretch_glyph (it, it->object, it->pixel_width,
32037 it->ascent + it->descent, ascent);
32038 }
32039 else
32040 append_glyph (it);
32041
32042
32043
32044
32045 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
32046 it->glyph_row->contains_overlapping_glyphs_p = true;
32047 }
32048 if (! stretched_p && it->pixel_width == 0)
32049
32050
32051 it->pixel_width = 1;
32052 }
32053 else if (it->char_to_display == '\n')
32054 {
32055
32056
32057
32058
32059 Lisp_Object height;
32060 Lisp_Object total_height = Qnil;
32061
32062 it->override_ascent = -1;
32063 it->pixel_width = 0;
32064 it->nglyphs = 0;
32065
32066 height = get_it_property (it, Qline_height);
32067
32068 if (CONSP (height)
32069 && CONSP (XCDR (height))
32070 && NILP (XCDR (XCDR (height))))
32071 {
32072 total_height = XCAR (XCDR (height));
32073 height = XCAR (height);
32074 }
32075 height = calc_line_height_property (it, height, font, boff, true);
32076
32077 if (it->override_ascent >= 0)
32078 {
32079 it->ascent = it->override_ascent;
32080 it->descent = it->override_descent;
32081 boff = it->override_boff;
32082 }
32083 else
32084 {
32085 if (FONT_TOO_HIGH (font))
32086 {
32087 it->ascent = font->pixel_size + boff - 1;
32088 it->descent = -boff + 1;
32089 if (it->descent < 0)
32090 it->descent = 0;
32091 }
32092 else
32093 {
32094 it->ascent = FONT_BASE (font) + boff;
32095 it->descent = FONT_DESCENT (font) - boff;
32096 }
32097 }
32098
32099 if (EQ (height, Qt))
32100 {
32101 if (it->descent > it->max_descent)
32102 {
32103 it->ascent += it->descent - it->max_descent;
32104 it->descent = it->max_descent;
32105 }
32106 if (it->ascent > it->max_ascent)
32107 {
32108 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32109 it->ascent = it->max_ascent;
32110 }
32111 it->phys_ascent = min (it->phys_ascent, it->ascent);
32112 it->phys_descent = min (it->phys_descent, it->descent);
32113 it->constrain_row_ascent_descent_p = true;
32114 extra_line_spacing = 0;
32115 }
32116 else
32117 {
32118 Lisp_Object spacing;
32119
32120 it->phys_ascent = it->ascent;
32121 it->phys_descent = it->descent;
32122
32123 if ((it->max_ascent > 0 || it->max_descent > 0)
32124 && face->box != FACE_NO_BOX
32125 && face->box_horizontal_line_width > 0)
32126 {
32127 it->ascent += face->box_horizontal_line_width;
32128 it->descent += face->box_horizontal_line_width;
32129 }
32130 if (!NILP (height)
32131 && XFIXNUM (height) > it->ascent + it->descent)
32132 it->ascent = XFIXNUM (height) - it->descent;
32133
32134 if (!NILP (total_height))
32135 spacing = calc_line_height_property (it, total_height, font,
32136 boff, false);
32137 else
32138 {
32139 spacing = get_it_property (it, Qline_spacing);
32140 spacing = calc_line_height_property (it, spacing, font,
32141 boff, false);
32142 }
32143 if (FIXNUMP (spacing))
32144 {
32145 extra_line_spacing = XFIXNUM (spacing);
32146 if (!NILP (total_height))
32147 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
32148 }
32149 }
32150 }
32151 else
32152 {
32153 if (font->space_width > 0)
32154 {
32155 int tab_width = it->tab_width * font->space_width;
32156 int x = it->current_x + it->continuation_lines_width;
32157 int x0 = x;
32158
32159 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32160 {
32161 x -= it->lnum_pixel_width;
32162
32163 if (x + it->stretch_adjust >= it->first_visible_x)
32164 x += it->stretch_adjust;
32165 }
32166
32167 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
32168
32169
32170
32171
32172 if (next_tab_x - x < font->space_width)
32173 next_tab_x += tab_width;
32174 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32175 {
32176 next_tab_x += it->lnum_pixel_width;
32177
32178
32179 if (x < it->first_visible_x)
32180 {
32181 next_tab_x -= it->first_visible_x - x;
32182 it->stretch_adjust = it->first_visible_x - x;
32183 }
32184 else
32185 next_tab_x -= it->stretch_adjust;
32186 }
32187
32188 it->pixel_width = next_tab_x - x0;
32189 it->nglyphs = 1;
32190 if (FONT_TOO_HIGH (font))
32191 {
32192 if (get_char_glyph_code (' ', font, &char2b))
32193 {
32194 pcm = get_per_char_metric (font, &char2b);
32195 if (pcm->width == 0
32196 && pcm->rbearing == 0 && pcm->lbearing == 0)
32197 pcm = NULL;
32198 }
32199
32200 if (pcm)
32201 {
32202 it->ascent = pcm->ascent + boff;
32203 it->descent = pcm->descent - boff;
32204 }
32205 else
32206 {
32207 it->ascent = font->pixel_size + boff - 1;
32208 it->descent = -boff + 1;
32209 }
32210 if (it->ascent < 0)
32211 it->ascent = 0;
32212 if (it->descent < 0)
32213 it->descent = 0;
32214 }
32215 else
32216 {
32217 it->ascent = FONT_BASE (font) + boff;
32218 it->descent = FONT_DESCENT (font) - boff;
32219 }
32220 it->phys_ascent = it->ascent;
32221 it->phys_descent = it->descent;
32222
32223 if (it->glyph_row)
32224 {
32225 append_stretch_glyph (it, it->object, it->pixel_width,
32226 it->ascent + it->descent, it->ascent);
32227 }
32228 }
32229 else
32230 {
32231 it->pixel_width = 0;
32232 it->nglyphs = 1;
32233 }
32234 }
32235
32236 if (FONT_TOO_HIGH (font))
32237 {
32238 int font_ascent, font_descent;
32239
32240
32241
32242
32243
32244
32245
32246
32247 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32248 it->max_ascent = max (it->max_ascent, font_ascent);
32249 it->max_descent = max (it->max_descent, font_descent);
32250 }
32251
32252 if (it->ascent < 0)
32253 it->ascent = 0;
32254 if (it->descent < 0)
32255 it->descent = 0;
32256 }
32257 else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
32258 {
32259
32260
32261
32262
32263
32264
32265
32266
32267 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32268 int boff;
32269 struct composition *cmp = composition_table[it->cmp_it.id];
32270 int glyph_len = cmp->glyph_len;
32271 struct font *font = face->font;
32272
32273 it->nglyphs = 1;
32274
32275
32276
32277
32278
32279
32280
32281
32282 if (! cmp->font || cmp->font != font)
32283 {
32284
32285
32286
32287
32288 int font_ascent, font_descent, font_height;
32289
32290 int leftmost, rightmost, lowest, highest;
32291 int lbearing, rbearing;
32292 int i, width, ascent, descent;
32293 int c;
32294 unsigned char2b;
32295 struct font_metrics *pcm;
32296 ptrdiff_t pos;
32297
32298 eassume (0 < glyph_len);
32299 do
32300 c = COMPOSITION_GLYPH (cmp, glyph_len - 1);
32301 while (c == '\t' && 0 < --glyph_len);
32302
32303 bool right_padded = glyph_len < cmp->glyph_len;
32304 for (i = 0; i < glyph_len; i++)
32305 {
32306 c = COMPOSITION_GLYPH (cmp, i);
32307 if (c != '\t')
32308 break;
32309 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32310 }
32311 bool left_padded = i > 0;
32312
32313 pos = (STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
32314 : IT_CHARPOS (*it));
32315
32316 bool font_not_found_p = font == NULL;
32317 if (font_not_found_p)
32318 {
32319 face = face->ascii_face;
32320 font = face->font;
32321 }
32322 boff = font->baseline_offset;
32323 if (font->vertical_centering)
32324 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32325 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32326 font_ascent += boff;
32327 font_descent -= boff;
32328 font_height = font_ascent + font_descent;
32329
32330 cmp->font = font;
32331
32332 pcm = NULL;
32333 if (! font_not_found_p)
32334 {
32335 get_char_face_and_encoding (it->f, c, it->face_id,
32336 &char2b, false);
32337 pcm = get_per_char_metric (font, &char2b);
32338 }
32339
32340
32341 if (pcm)
32342 {
32343 width = cmp->glyph_len > 0 ? pcm->width : 0;
32344 ascent = pcm->ascent;
32345 descent = pcm->descent;
32346 lbearing = pcm->lbearing;
32347 rbearing = pcm->rbearing;
32348 }
32349 else
32350 {
32351 width = cmp->glyph_len > 0 ? font->space_width : 0;
32352 ascent = FONT_BASE (font);
32353 descent = FONT_DESCENT (font);
32354 lbearing = 0;
32355 rbearing = width;
32356 }
32357
32358 rightmost = width;
32359 leftmost = 0;
32360 lowest = - descent + boff;
32361 highest = ascent + boff;
32362
32363 if (! font_not_found_p
32364 && font->default_ascent
32365 && CHAR_TABLE_P (Vuse_default_ascent)
32366 && !NILP (Faref (Vuse_default_ascent,
32367 make_fixnum (it->char_to_display))))
32368 highest = font->default_ascent + boff;
32369
32370
32371
32372
32373 cmp->offsets[i * 2] = 0;
32374 cmp->offsets[i * 2 + 1] = boff;
32375 cmp->lbearing = lbearing;
32376 cmp->rbearing = rbearing;
32377
32378
32379 for (i++; i < glyph_len; i++)
32380 {
32381 int left, right, btm, top;
32382 int ch = COMPOSITION_GLYPH (cmp, i);
32383 int face_id;
32384 struct face *this_face;
32385
32386 if (ch == '\t')
32387 ch = ' ';
32388 face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
32389 this_face = FACE_FROM_ID (it->f, face_id);
32390 font = this_face->font;
32391
32392 if (font == NULL)
32393 pcm = NULL;
32394 else
32395 {
32396 get_char_face_and_encoding (it->f, ch, face_id,
32397 &char2b, false);
32398 pcm = get_per_char_metric (font, &char2b);
32399 }
32400 if (! pcm)
32401 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32402 else
32403 {
32404 width = pcm->width;
32405 ascent = pcm->ascent;
32406 descent = pcm->descent;
32407 lbearing = pcm->lbearing;
32408 rbearing = pcm->rbearing;
32409 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
32410 {
32411
32412
32413 left = (leftmost + rightmost - width) / 2;
32414 btm = - descent + boff;
32415 if (font->relative_compose
32416 && (! CHAR_TABLE_P (Vignore_relative_composition)
32417 || NILP (Faref (Vignore_relative_composition,
32418 make_fixnum (ch)))))
32419 {
32420
32421 if (- descent >= font->relative_compose)
32422
32423 btm = highest + 1;
32424 else if (ascent <= 0)
32425
32426 btm = lowest - 1 - ascent - descent;
32427 }
32428 }
32429 else
32430 {
32431
32432
32433
32434
32435
32436
32437
32438
32439
32440
32441
32442
32443
32444
32445
32446 int rule = COMPOSITION_RULE (cmp, i);
32447 int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
32448
32449 COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
32450 grefx = gref % 3, nrefx = nref % 3;
32451 grefy = gref / 3, nrefy = nref / 3;
32452 if (xoff)
32453 xoff = font_height * (xoff - 128) / 256;
32454 if (yoff)
32455 yoff = font_height * (yoff - 128) / 256;
32456
32457 left = (leftmost
32458 + grefx * (rightmost - leftmost) / 2
32459 - nrefx * width / 2
32460 + xoff);
32461
32462 btm = ((grefy == 0 ? highest
32463 : grefy == 1 ? 0
32464 : grefy == 2 ? lowest
32465 : (highest + lowest) / 2)
32466 - (nrefy == 0 ? ascent + descent
32467 : nrefy == 1 ? descent - boff
32468 : nrefy == 2 ? 0
32469 : (ascent + descent) / 2)
32470 + yoff);
32471 }
32472
32473 cmp->offsets[i * 2] = left;
32474 cmp->offsets[i * 2 + 1] = btm + descent;
32475
32476
32477 if (width > 0)
32478 {
32479 right = left + width;
32480 if (left < leftmost)
32481 leftmost = left;
32482 if (right > rightmost)
32483 rightmost = right;
32484 }
32485 top = btm + descent + ascent;
32486 if (top > highest)
32487 highest = top;
32488 if (btm < lowest)
32489 lowest = btm;
32490
32491 if (cmp->lbearing > left + lbearing)
32492 cmp->lbearing = left + lbearing;
32493 if (cmp->rbearing < left + rbearing)
32494 cmp->rbearing = left + rbearing;
32495 }
32496 }
32497
32498
32499
32500
32501 if (leftmost < 0)
32502 {
32503 for (i = 0; i < cmp->glyph_len; i++)
32504 cmp->offsets[i * 2] -= leftmost;
32505 rightmost -= leftmost;
32506 cmp->lbearing -= leftmost;
32507 cmp->rbearing -= leftmost;
32508 }
32509
32510 if (left_padded && cmp->lbearing < 0)
32511 {
32512 for (i = 0; i < cmp->glyph_len; i++)
32513 cmp->offsets[i * 2] -= cmp->lbearing;
32514 rightmost -= cmp->lbearing;
32515 cmp->rbearing -= cmp->lbearing;
32516 cmp->lbearing = 0;
32517 }
32518 if (right_padded && rightmost < cmp->rbearing)
32519 {
32520 rightmost = cmp->rbearing;
32521 }
32522
32523 cmp->pixel_width = rightmost;
32524 cmp->ascent = highest;
32525 cmp->descent = - lowest;
32526 if (cmp->ascent < font_ascent)
32527 cmp->ascent = font_ascent;
32528 if (cmp->descent < font_descent)
32529 cmp->descent = font_descent;
32530 }
32531
32532 if (it->glyph_row
32533 && (cmp->lbearing < 0
32534 || cmp->rbearing > cmp->pixel_width))
32535 it->glyph_row->contains_overlapping_glyphs_p = true;
32536
32537 it->pixel_width = cmp->pixel_width;
32538 it->ascent = it->phys_ascent = cmp->ascent;
32539 it->descent = it->phys_descent = cmp->descent;
32540 IT_APPLY_FACE_BOX(it, face);
32541
32542
32543
32544 if (face->overline_p)
32545 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32546
32547 take_vertical_position_into_account (it);
32548 if (it->ascent < 0)
32549 it->ascent = 0;
32550 if (it->descent < 0)
32551 it->descent = 0;
32552
32553 if (it->glyph_row && cmp->glyph_len > 0)
32554 append_composite_glyph (it);
32555 }
32556 else if (it->what == IT_COMPOSITION)
32557 {
32558
32559 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32560 Lisp_Object gstring;
32561 struct font_metrics metrics;
32562
32563 it->nglyphs = 1;
32564
32565 gstring = composition_gstring_from_id (it->cmp_it.id);
32566 it->pixel_width
32567 = composition_gstring_width (gstring, it->cmp_it.from, it->cmp_it.to,
32568 &metrics);
32569 if (it->pixel_width == 0)
32570 {
32571 it->glyph_not_available_p = true;
32572 it->phys_ascent = it->ascent;
32573 it->phys_descent = it->descent;
32574 it->pixel_width = face->font->space_width;
32575 }
32576 else
32577 {
32578 if (it->glyph_row
32579 && (metrics.lbearing < 0 || metrics.rbearing > metrics.width))
32580 it->glyph_row->contains_overlapping_glyphs_p = true;
32581 it->ascent = it->phys_ascent = metrics.ascent;
32582 it->descent = it->phys_descent = metrics.descent;
32583 }
32584 IT_APPLY_FACE_BOX(it, face);
32585
32586
32587
32588 if (face->overline_p)
32589 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32590 take_vertical_position_into_account (it);
32591 if (it->ascent < 0)
32592 it->ascent = 0;
32593 if (it->descent < 0)
32594 it->descent = 0;
32595
32596 if (it->glyph_row)
32597 append_composite_glyph (it);
32598 }
32599 else if (it->what == IT_GLYPHLESS)
32600 produce_glyphless_glyph (it, false, Qnil);
32601 else if (it->what == IT_IMAGE)
32602 produce_image_glyph (it);
32603 else if (it->what == IT_STRETCH)
32604 produce_stretch_glyph (it);
32605 else if (it->what == IT_XWIDGET)
32606 produce_xwidget_glyph (it);
32607
32608 done:
32609
32610
32611 eassert (it->ascent >= 0 && it->descent >= 0);
32612 if (it->area == TEXT_AREA)
32613 it->current_x += it->pixel_width;
32614
32615 if (extra_line_spacing > 0)
32616 {
32617 it->descent += extra_line_spacing;
32618 if (extra_line_spacing > it->max_extra_line_spacing)
32619 it->max_extra_line_spacing = extra_line_spacing;
32620 }
32621
32622 it->max_ascent = max (it->max_ascent, it->ascent);
32623 it->max_descent = max (it->max_descent, it->descent);
32624 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
32625 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
32626 }
32627
32628
32629
32630
32631
32632
32633 void
32634 gui_write_glyphs (struct window *w, struct glyph_row *updated_row,
32635 struct glyph *start, enum glyph_row_area updated_area, int len)
32636 {
32637 int x, hpos, chpos = w->phys_cursor.hpos;
32638
32639 eassert (updated_row);
32640
32641
32642
32643 if (!updated_row->reversed_p && chpos < 0)
32644 chpos = 0;
32645 if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
32646 chpos = updated_row->used[TEXT_AREA] - 1;
32647
32648 block_input ();
32649
32650
32651
32652 hpos = start - updated_row->glyphs[updated_area];
32653 x = draw_glyphs (w, w->output_cursor.x,
32654 updated_row, updated_area,
32655 hpos, hpos + len,
32656 DRAW_NORMAL_TEXT, 0);
32657
32658
32659 if (updated_area == TEXT_AREA
32660 && w->phys_cursor_on_p
32661 && w->phys_cursor.vpos == w->output_cursor.vpos
32662 && chpos >= hpos
32663 && chpos < hpos + len)
32664 w->phys_cursor_on_p = false;
32665
32666 unblock_input ();
32667
32668
32669 w->output_cursor.hpos += len;
32670 w->output_cursor.x = x;
32671 }
32672
32673
32674
32675
32676
32677 void
32678 gui_insert_glyphs (struct window *w, struct glyph_row *updated_row,
32679 struct glyph *start, enum glyph_row_area updated_area, int len)
32680 {
32681 struct frame *f;
32682 int line_height, shift_by_width, shifted_region_width;
32683 struct glyph_row *row;
32684 struct glyph *glyph;
32685 int frame_x, frame_y;
32686 ptrdiff_t hpos;
32687
32688 eassert (updated_row);
32689 block_input ();
32690 f = XFRAME (WINDOW_FRAME (w));
32691
32692
32693 row = updated_row;
32694 line_height = row->height;
32695
32696
32697 shift_by_width = 0;
32698 for (glyph = start; glyph < start + len; ++glyph)
32699 shift_by_width += glyph->pixel_width;
32700
32701
32702 shifted_region_width = (window_box_width (w, updated_area)
32703 - w->output_cursor.x
32704 - shift_by_width);
32705
32706
32707 frame_x = window_box_left (w, updated_area) + w->output_cursor.x;
32708 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->output_cursor.y);
32709
32710 FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
32711 line_height, shift_by_width);
32712
32713
32714 hpos = start - row->glyphs[updated_area];
32715 draw_glyphs (w, w->output_cursor.x, row, updated_area,
32716 hpos, hpos + len,
32717 DRAW_NORMAL_TEXT, 0);
32718
32719
32720 w->output_cursor.hpos += len;
32721 w->output_cursor.x += shift_by_width;
32722 unblock_input ();
32723 }
32724
32725
32726
32727
32728
32729
32730
32731
32732
32733
32734 void
32735 gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
32736 enum glyph_row_area updated_area, int to_x)
32737 {
32738 struct frame *f;
32739 int max_x, min_y, max_y;
32740 int from_x, from_y, to_y;
32741 struct face *face;
32742
32743 eassert (updated_row);
32744 f = XFRAME (w->frame);
32745 face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
32746
32747 if (updated_row->full_width_p)
32748 max_x = (WINDOW_PIXEL_WIDTH (w)
32749 - (updated_row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
32750 else
32751 max_x = window_box_width (w, updated_area);
32752 max_y = window_text_bottom_y (w);
32753
32754
32755
32756 if (to_x == 0)
32757 return;
32758 else if (to_x < 0)
32759 to_x = max_x;
32760 else
32761 to_x = min (to_x, max_x);
32762
32763 to_y = min (max_y, w->output_cursor.y + updated_row->height);
32764
32765
32766 if (!updated_row->full_width_p)
32767 notice_overwritten_cursor (w, updated_area,
32768 w->output_cursor.x, -1,
32769 updated_row->y,
32770 MATRIX_ROW_BOTTOM_Y (updated_row));
32771
32772 from_x = w->output_cursor.x;
32773
32774
32775 if (updated_row->full_width_p)
32776 {
32777 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
32778 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
32779 }
32780 else
32781 {
32782 int area_left = window_box_left (w, updated_area);
32783 from_x += area_left;
32784 to_x += area_left;
32785 }
32786
32787 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
32788 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, w->output_cursor.y));
32789 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
32790
32791
32792 if (to_x > from_x && to_y > from_y)
32793 {
32794 block_input ();
32795 FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
32796 to_x - from_x, to_y - from_y);
32797
32798 if (face && !updated_row->stipple_p)
32799 updated_row->stipple_p = face->stipple;
32800 unblock_input ();
32801 }
32802 }
32803
32804 #endif
32805
32806
32807
32808
32809
32810
32811
32812
32813
32814
32815
32816 static enum text_cursor_kinds
32817 get_specified_cursor_type (Lisp_Object arg, int *width)
32818 {
32819 enum text_cursor_kinds type;
32820
32821 if (NILP (arg))
32822 return NO_CURSOR;
32823
32824 if (EQ (arg, Qbox))
32825 return FILLED_BOX_CURSOR;
32826
32827 if (EQ (arg, Qhollow))
32828 return HOLLOW_BOX_CURSOR;
32829
32830 if (EQ (arg, Qbar))
32831 {
32832 *width = 2;
32833 return BAR_CURSOR;
32834 }
32835
32836 if (EQ (arg, Qhbar))
32837 {
32838 *width = 2;
32839 return HBAR_CURSOR;
32840 }
32841
32842 if (CONSP (arg)
32843 && RANGED_FIXNUMP (0, XCDR (arg), INT_MAX))
32844 {
32845 *width = XFIXNUM (XCDR (arg));
32846
32847 if (EQ (XCAR (arg), Qbox))
32848 return FILLED_BOX_CURSOR;
32849 else if (EQ (XCAR (arg), Qbar))
32850 return BAR_CURSOR;
32851 else if (EQ (XCAR (arg), Qhbar))
32852 return HBAR_CURSOR;
32853 }
32854
32855
32856
32857
32858 type = HOLLOW_BOX_CURSOR;
32859
32860 return type;
32861 }
32862
32863
32864 void
32865 set_frame_cursor_types (struct frame *f, Lisp_Object arg)
32866 {
32867 int width = 1;
32868 Lisp_Object tem;
32869
32870 FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
32871 FRAME_CURSOR_WIDTH (f) = width;
32872
32873
32874
32875 tem = Fassoc (arg, Vblink_cursor_alist, Qnil);
32876 if (!NILP (tem))
32877 {
32878 FRAME_BLINK_OFF_CURSOR (f)
32879 = get_specified_cursor_type (XCDR (tem), &width);
32880 FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
32881 }
32882 else
32883 FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
32884
32885
32886 f->cursor_type_changed = true;
32887 }
32888
32889
32890 #ifdef HAVE_WINDOW_SYSTEM
32891
32892
32893
32894
32895
32896
32897
32898
32899
32900
32901
32902
32903 static enum text_cursor_kinds
32904 get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
32905 bool *active_cursor)
32906 {
32907 struct frame *f = XFRAME (w->frame);
32908 struct buffer *b = XBUFFER (w->contents);
32909 int cursor_type = DEFAULT_CURSOR;
32910 Lisp_Object alt_cursor;
32911 bool non_selected = false;
32912
32913 *active_cursor = true;
32914
32915
32916 if (cursor_in_echo_area
32917 && FRAME_HAS_MINIBUF_P (f)
32918 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
32919 {
32920 if (w == XWINDOW (echo_area_window))
32921 {
32922 if (EQ (BVAR (b, cursor_type), Qt) || NILP (BVAR (b, cursor_type)))
32923 {
32924 *width = FRAME_CURSOR_WIDTH (f);
32925 return FRAME_DESIRED_CURSOR (f);
32926 }
32927 else
32928 return get_specified_cursor_type (BVAR (b, cursor_type), width);
32929 }
32930
32931 *active_cursor = false;
32932 non_selected = true;
32933 }
32934
32935
32936 else if (w != XWINDOW (f->selected_window)
32937 || f != FRAME_DISPLAY_INFO (f)->highlight_frame)
32938 {
32939 *active_cursor = false;
32940
32941 if (MINI_WINDOW_P (w) &&
32942 (minibuf_level == 0
32943 || is_minibuffer (0, w->contents)))
32944 return NO_CURSOR;
32945
32946 non_selected = true;
32947 }
32948
32949
32950 if (NILP (BVAR (b, cursor_type)))
32951 return NO_CURSOR;
32952
32953
32954 if (EQ (BVAR (b, cursor_type), Qt))
32955 {
32956 cursor_type = FRAME_DESIRED_CURSOR (f);
32957 *width = FRAME_CURSOR_WIDTH (f);
32958 }
32959 else
32960 cursor_type = get_specified_cursor_type (BVAR (b, cursor_type), width);
32961
32962
32963
32964 if (non_selected)
32965 {
32966 alt_cursor = BVAR (b, cursor_in_non_selected_windows);
32967 if (!EQ (Qt, alt_cursor))
32968 return get_specified_cursor_type (alt_cursor, width);
32969
32970 if (cursor_type == FILLED_BOX_CURSOR)
32971 cursor_type = HOLLOW_BOX_CURSOR;
32972 else if (cursor_type == BAR_CURSOR && *width > 1)
32973 --*width;
32974 return cursor_type;
32975 }
32976
32977
32978 if (!w->cursor_off_p)
32979 {
32980 if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
32981 return NO_CURSOR;
32982 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
32983 {
32984 if (cursor_type == FILLED_BOX_CURSOR)
32985 {
32986
32987
32988
32989
32990 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
32991 if (img != NULL && IMAGEP (img->spec))
32992 {
32993
32994
32995
32996
32997
32998
32999 if (!img->mask
33000 || (CONSP (BVAR (b, cursor_type))
33001 && img->width > max (*width, WINDOW_FRAME_COLUMN_WIDTH (w))
33002 && img->height > max (*width, WINDOW_FRAME_LINE_HEIGHT (w))))
33003 cursor_type = HOLLOW_BOX_CURSOR;
33004 }
33005 }
33006 else if (cursor_type != NO_CURSOR)
33007 {
33008
33009
33010
33011 cursor_type = HOLLOW_BOX_CURSOR;
33012 }
33013 }
33014 return cursor_type;
33015 }
33016
33017
33018
33019
33020 if ((alt_cursor = Fassoc (BVAR (b, cursor_type), Vblink_cursor_alist, Qnil), !NILP (alt_cursor)))
33021 return get_specified_cursor_type (XCDR (alt_cursor), width);
33022
33023
33024 if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
33025 {
33026 *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
33027 return FRAME_BLINK_OFF_CURSOR (f);
33028 }
33029
33030 #if false
33031
33032
33033
33034
33035
33036
33037
33038
33039
33040
33041 if (cursor_type == FILLED_BOX_CURSOR)
33042 return HOLLOW_BOX_CURSOR;
33043
33044 if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
33045 {
33046 *width = 1;
33047 return cursor_type;
33048 }
33049 #endif
33050
33051 return NO_CURSOR;
33052 }
33053
33054
33055
33056
33057
33058
33059
33060
33061
33062 static void
33063 notice_overwritten_cursor (struct window *w, enum glyph_row_area area,
33064 int x0, int x1, int y0, int y1)
33065 {
33066 int cx0, cx1, cy0, cy1;
33067 struct glyph_row *row;
33068
33069 if (!w->phys_cursor_on_p)
33070 return;
33071 if (area != TEXT_AREA)
33072 return;
33073
33074 if (w->phys_cursor.vpos < 0
33075 || w->phys_cursor.vpos >= w->current_matrix->nrows
33076 || (row = w->current_matrix->rows + w->phys_cursor.vpos,
33077 !(row->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (row))))
33078 return;
33079
33080 if (row->cursor_in_fringe_p)
33081 {
33082 row->cursor_in_fringe_p = false;
33083 draw_fringe_bitmap (w, row, row->reversed_p);
33084 w->phys_cursor_on_p = false;
33085 return;
33086 }
33087
33088 cx0 = w->phys_cursor.x;
33089 cx1 = cx0 + w->phys_cursor_width;
33090 if (x0 > cx0 || (x1 >= 0 && x1 < cx1))
33091 return;
33092
33093
33094
33095
33096
33097
33098
33099
33100
33101
33102
33103
33104
33105
33106
33107
33108
33109 cy0 = w->phys_cursor.y;
33110 cy1 = cy0 + w->phys_cursor_height;
33111 if ((y0 < cy0 || y0 >= cy1) && (y1 <= cy0 || y1 >= cy1))
33112 return;
33113
33114 w->phys_cursor_on_p = false;
33115 }
33116
33117 #endif
33118
33119
33120
33121
33122
33123
33124 #ifdef HAVE_WINDOW_SYSTEM
33125
33126
33127
33128
33129
33130 void
33131 gui_fix_overlapping_area (struct window *w, struct glyph_row *row,
33132 enum glyph_row_area area, int overlaps)
33133 {
33134 int i, x;
33135
33136 block_input ();
33137
33138 x = 0;
33139 for (i = 0; i < row->used[area];)
33140 {
33141 if (row->glyphs[area][i].overlaps_vertically_p)
33142 {
33143 int start = i, start_x = x;
33144
33145 do
33146 {
33147 x += row->glyphs[area][i].pixel_width;
33148 ++i;
33149 }
33150 while (i < row->used[area]
33151 && row->glyphs[area][i].overlaps_vertically_p);
33152
33153 draw_glyphs (w, start_x, row, area,
33154 start, i,
33155 DRAW_NORMAL_TEXT, overlaps);
33156 }
33157 else
33158 {
33159 x += row->glyphs[area][i].pixel_width;
33160 ++i;
33161 }
33162 }
33163
33164 unblock_input ();
33165 }
33166
33167
33168
33169
33170
33171
33172 void
33173 draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
33174 enum draw_glyphs_face hl)
33175 {
33176
33177
33178
33179 if ((row->reversed_p
33180 ? (w->phys_cursor.hpos >= 0)
33181 : (w->phys_cursor.hpos < row->used[TEXT_AREA])))
33182 {
33183 bool on_p = w->phys_cursor_on_p;
33184 int x1;
33185 int hpos = w->phys_cursor.hpos;
33186
33187
33188
33189
33190 if (!row->reversed_p && hpos < 0)
33191 hpos = 0;
33192 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33193 hpos = row->used[TEXT_AREA] - 1;
33194
33195 x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, hpos, hpos + 1,
33196 hl, 0);
33197 w->phys_cursor_on_p = on_p;
33198
33199 if (hl == DRAW_CURSOR)
33200 w->phys_cursor_width = x1 - w->phys_cursor.x;
33201
33202
33203
33204 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
33205 {
33206 w->phys_cursor_width = x1 - w->phys_cursor.x;
33207
33208 if (row > w->current_matrix->rows
33209 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
33210 gui_fix_overlapping_area (w, row - 1, TEXT_AREA,
33211 OVERLAPS_ERASED_CURSOR);
33212
33213 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
33214 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
33215 gui_fix_overlapping_area (w, row + 1, TEXT_AREA,
33216 OVERLAPS_ERASED_CURSOR);
33217 }
33218 }
33219 }
33220
33221
33222
33223
33224 void
33225 erase_phys_cursor (struct window *w)
33226 {
33227 struct frame *f = XFRAME (w->frame);
33228 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
33229 int hpos = w->phys_cursor.hpos;
33230 int vpos = w->phys_cursor.vpos;
33231 bool mouse_face_here_p = false;
33232 struct glyph_matrix *active_glyphs = w->current_matrix;
33233 struct glyph_row *cursor_row;
33234 struct glyph *cursor_glyph;
33235 enum draw_glyphs_face hl;
33236
33237
33238
33239 if (w->phys_cursor_type == NO_CURSOR)
33240 goto mark_cursor_off;
33241
33242
33243
33244 if (vpos >= active_glyphs->nrows)
33245 goto mark_cursor_off;
33246
33247
33248
33249 cursor_row = MATRIX_ROW (active_glyphs, vpos);
33250 if (!cursor_row->enabled_p)
33251 goto mark_cursor_off;
33252
33253
33254
33255 cursor_row->visible_height = min (cursor_row->visible_height,
33256 window_text_bottom_y (w) - cursor_row->y);
33257
33258
33259
33260
33261 if (cursor_row->visible_height <= 0)
33262 goto mark_cursor_off;
33263
33264
33265 if (cursor_row->cursor_in_fringe_p)
33266 {
33267 cursor_row->cursor_in_fringe_p = false;
33268 draw_fringe_bitmap (w, cursor_row, cursor_row->reversed_p);
33269 goto mark_cursor_off;
33270 }
33271
33272
33273
33274
33275
33276
33277 if ((cursor_row->reversed_p
33278 ? (w->phys_cursor.hpos < 0)
33279 : (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])))
33280 goto mark_cursor_off;
33281
33282
33283
33284
33285 if (!cursor_row->reversed_p && hpos < 0)
33286 hpos = 0;
33287 if (cursor_row->reversed_p && hpos >= cursor_row->used[TEXT_AREA])
33288 hpos = cursor_row->used[TEXT_AREA] - 1;
33289
33290
33291
33292 if (! NILP (hlinfo->mouse_face_window)
33293 && coords_in_mouse_face_p (w, hpos, vpos)
33294
33295
33296
33297 && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0)
33298 mouse_face_here_p = true;
33299
33300 #ifdef HAVE_WINDOW_SYSTEM
33301
33302
33303
33304
33305 if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) && mouse_face_here_p)
33306 {
33307 w->phys_cursor_on_p = false;
33308 w->phys_cursor_type = NO_CURSOR;
33309 show_mouse_face (MOUSE_HL_INFO (WINDOW_XFRAME (w)), DRAW_MOUSE_FACE);
33310 return;
33311 }
33312 #endif
33313
33314
33315 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
33316 {
33317 int x, y;
33318 int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w);
33319 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
33320 int width;
33321
33322 cursor_glyph = get_phys_cursor_glyph (w);
33323 if (cursor_glyph == NULL)
33324 goto mark_cursor_off;
33325
33326 width = cursor_glyph->pixel_width;
33327 x = w->phys_cursor.x;
33328 if (x < 0)
33329 {
33330 width += x;
33331 x = 0;
33332 }
33333 width = min (width, window_box_width (w, TEXT_AREA) - x);
33334 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (tab_line_height, max (header_line_height, cursor_row->y)));
33335 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
33336
33337 if (width > 0)
33338 FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height);
33339 }
33340
33341
33342 if (mouse_face_here_p)
33343 hl = DRAW_MOUSE_FACE;
33344 else
33345 hl = DRAW_NORMAL_TEXT;
33346 draw_phys_cursor_glyph (w, cursor_row, hl);
33347
33348 mark_cursor_off:
33349 w->phys_cursor_on_p = false;
33350 w->phys_cursor_type = NO_CURSOR;
33351 }
33352
33353
33354
33355
33356
33357
33358 void
33359 display_and_set_cursor (struct window *w, bool on,
33360 int hpos, int vpos, int x, int y)
33361 {
33362 struct frame *f = XFRAME (w->frame);
33363 int new_cursor_type;
33364 int new_cursor_width UNINIT;
33365 bool active_cursor;
33366 struct glyph_row *glyph_row;
33367 struct glyph *glyph;
33368
33369
33370
33371
33372
33373 if (! FRAME_VISIBLE_P (f)
33374 || vpos >= w->current_matrix->nrows
33375 || hpos >= w->current_matrix->matrix_w)
33376 return;
33377
33378
33379 if (!on && !w->phys_cursor_on_p)
33380 return;
33381
33382 glyph_row = MATRIX_ROW (w->current_matrix, vpos);
33383
33384
33385 if (!glyph_row->enabled_p)
33386 {
33387 w->phys_cursor_on_p = false;
33388 return;
33389 }
33390
33391
33392
33393
33394
33395
33396
33397
33398
33399 if (FRAME_GARBAGED_P (f))
33400 {
33401 if (on)
33402 {
33403 w->phys_cursor.x = x;
33404 w->phys_cursor.y = glyph_row->y;
33405 w->phys_cursor.hpos = hpos;
33406 w->phys_cursor.vpos = vpos;
33407 }
33408 return;
33409 }
33410
33411 glyph = NULL;
33412 if (0 <= hpos && hpos < glyph_row->used[TEXT_AREA])
33413 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
33414
33415 eassert (input_blocked_p ());
33416
33417
33418 new_cursor_type = get_window_cursor_type (w, glyph,
33419 &new_cursor_width, &active_cursor);
33420
33421
33422
33423
33424 if (w->phys_cursor_on_p
33425 && (!on
33426 || w->phys_cursor.x != x
33427 || w->phys_cursor.y != y
33428
33429
33430
33431 || hpos < 0
33432 || new_cursor_type != w->phys_cursor_type
33433 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
33434 && new_cursor_width != w->phys_cursor_width)))
33435 erase_phys_cursor (w);
33436
33437
33438
33439
33440
33441
33442 if (on)
33443 {
33444 w->phys_cursor_ascent = glyph_row->ascent;
33445 w->phys_cursor_height = glyph_row->height;
33446
33447
33448
33449 w->phys_cursor.x = x;
33450 w->phys_cursor.y = glyph_row->y;
33451 w->phys_cursor.hpos = hpos;
33452 w->phys_cursor.vpos = vpos;
33453 }
33454
33455 FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
33456 new_cursor_type, new_cursor_width,
33457 on, active_cursor);
33458 }
33459
33460
33461
33462
33463
33464 static void
33465 update_window_cursor (struct window *w, bool on)
33466 {
33467
33468
33469 if (w->current_matrix)
33470 {
33471 int hpos = w->phys_cursor.hpos;
33472 int vpos = w->phys_cursor.vpos;
33473 struct glyph_row *row;
33474
33475 if (vpos >= w->current_matrix->nrows
33476 || hpos >= w->current_matrix->matrix_w)
33477 return;
33478
33479 row = MATRIX_ROW (w->current_matrix, vpos);
33480
33481
33482
33483
33484 if (!row->reversed_p && hpos < 0)
33485 hpos = 0;
33486 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33487 hpos = row->used[TEXT_AREA] - 1;
33488
33489 block_input ();
33490 display_and_set_cursor (w, on, hpos, vpos,
33491 w->phys_cursor.x, w->phys_cursor.y);
33492 unblock_input ();
33493 }
33494 }
33495
33496
33497
33498
33499
33500 static void
33501 update_cursor_in_window_tree (struct window *w, bool on_p)
33502 {
33503 while (w)
33504 {
33505 if (WINDOWP (w->contents))
33506 update_cursor_in_window_tree (XWINDOW (w->contents), on_p);
33507 else
33508 update_window_cursor (w, on_p);
33509
33510 w = NILP (w->next) ? 0 : XWINDOW (w->next);
33511 }
33512 }
33513
33514
33515
33516
33517
33518
33519 void
33520 gui_update_cursor (struct frame *f, bool on_p)
33521 {
33522 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
33523 }
33524
33525
33526
33527
33528
33529
33530
33531 void
33532 gui_clear_cursor (struct window *w)
33533 {
33534 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
33535 update_window_cursor (w, false);
33536 }
33537
33538 #endif
33539
33540
33541
33542 static void
33543 draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
33544 int start_hpos, int end_hpos,
33545 enum draw_glyphs_face draw)
33546 {
33547 #ifdef HAVE_WINDOW_SYSTEM
33548 if (FRAME_WINDOW_P (XFRAME (w->frame)))
33549 {
33550 draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0);
33551 return;
33552 }
33553 #endif
33554
33555 tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
33556 }
33557
33558
33559
33560 static void
33561 show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
33562 {
33563
33564
33565 if (!WINDOWP (hlinfo->mouse_face_window))
33566 return;
33567
33568 struct window *w = XWINDOW (hlinfo->mouse_face_window);
33569 struct frame *f = XFRAME (WINDOW_FRAME (w));
33570
33571
33572 if (f != hlinfo->mouse_face_mouse_frame)
33573 return;
33574
33575 if (
33576
33577 w->current_matrix != NULL
33578
33579 && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
33580
33581
33582 && hlinfo->mouse_face_end_row < w->current_matrix->nrows)
33583 {
33584 bool phys_cursor_on_p = w->phys_cursor_on_p;
33585 #ifdef HAVE_WINDOW_SYSTEM
33586 int mouse_off = 0;
33587 #endif
33588 struct glyph_row *row, *first, *last;
33589
33590 first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
33591 last = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row);
33592
33593 for (row = first; row <= last && row->enabled_p; ++row)
33594 {
33595 int start_hpos, end_hpos, start_x;
33596
33597
33598 if (row == first)
33599 {
33600
33601
33602
33603
33604 if (!row->reversed_p)
33605 {
33606 start_hpos = hlinfo->mouse_face_beg_col;
33607 start_x = hlinfo->mouse_face_beg_x;
33608 }
33609 else if (row == last)
33610 {
33611 start_hpos = hlinfo->mouse_face_end_col;
33612 start_x = hlinfo->mouse_face_end_x;
33613 }
33614 else
33615 {
33616 start_hpos = 0;
33617 start_x = 0;
33618 }
33619 }
33620 else if (row->reversed_p && row == last)
33621 {
33622 start_hpos = hlinfo->mouse_face_end_col;
33623 start_x = hlinfo->mouse_face_end_x;
33624 }
33625 else
33626 {
33627 start_hpos = 0;
33628 start_x = 0;
33629 }
33630
33631 if (row == last)
33632 {
33633 if (!row->reversed_p)
33634 end_hpos = hlinfo->mouse_face_end_col;
33635 else if (row == first)
33636 end_hpos = hlinfo->mouse_face_beg_col;
33637 else
33638 {
33639 end_hpos = row->used[TEXT_AREA];
33640 if (draw == DRAW_NORMAL_TEXT)
33641 row->fill_line_p = true;
33642 }
33643 }
33644 else if (row->reversed_p && row == first)
33645 end_hpos = hlinfo->mouse_face_beg_col;
33646 else
33647 {
33648 end_hpos = row->used[TEXT_AREA];
33649 if (draw == DRAW_NORMAL_TEXT)
33650 row->fill_line_p = true;
33651 }
33652
33653 if (end_hpos > start_hpos)
33654 {
33655 draw_row_with_mouse_face (w, start_x, row,
33656 start_hpos, end_hpos, draw);
33657
33658 row->mouse_face_p
33659 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
33660 }
33661 #ifdef HAVE_WINDOW_SYSTEM
33662
33663 if ((MATRIX_ROW_VPOS (row, w->current_matrix) == w->phys_cursor.vpos)
33664
33665
33666 && !w->pseudo_window_p
33667 && draw == DRAW_MOUSE_FACE)
33668 get_cursor_offset_for_mouse_face (w, row, &mouse_off);
33669 #endif
33670 }
33671
33672
33673
33674 if (FRAME_WINDOW_P (f)
33675 && phys_cursor_on_p && !w->phys_cursor_on_p)
33676 {
33677 #ifdef HAVE_WINDOW_SYSTEM
33678 int hpos = w->phys_cursor.hpos;
33679 int old_phys_cursor_x = w->phys_cursor.x;
33680
33681
33682
33683
33684 if (!row->reversed_p && hpos < 0)
33685 hpos = 0;
33686 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33687 hpos = row->used[TEXT_AREA] - 1;
33688
33689 block_input ();
33690 display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
33691 w->phys_cursor.x + mouse_off,
33692 w->phys_cursor.y);
33693
33694
33695 w->phys_cursor.x = old_phys_cursor_x;
33696 unblock_input ();
33697 #endif
33698 }
33699 }
33700
33701 #ifdef HAVE_WINDOW_SYSTEM
33702
33703 if (FRAME_WINDOW_P (f) && NILP (track_mouse))
33704 {
33705 if (draw == DRAW_NORMAL_TEXT
33706 #ifndef HAVE_EXT_TOOL_BAR
33707 && !EQ (hlinfo->mouse_face_window, f->tool_bar_window)
33708 #endif
33709 && !EQ (hlinfo->mouse_face_window, f->tab_bar_window))
33710 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->text_cursor);
33711 else
33712 if (draw == DRAW_MOUSE_FACE)
33713 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->hand_cursor);
33714 else
33715 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->nontext_cursor);
33716 }
33717 #endif
33718 }
33719
33720
33721
33722
33723
33724
33725 bool
33726 clear_mouse_face (Mouse_HLInfo *hlinfo)
33727 {
33728 bool cleared
33729 = !hlinfo->mouse_face_hidden && !NILP (hlinfo->mouse_face_window);
33730 if (cleared)
33731 show_mouse_face (hlinfo, DRAW_NORMAL_TEXT);
33732 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
33733 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
33734 hlinfo->mouse_face_window = Qnil;
33735 hlinfo->mouse_face_overlay = Qnil;
33736 return cleared;
33737 }
33738
33739
33740
33741 static bool
33742 coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
33743 {
33744 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
33745
33746
33747 if (!(WINDOWP (hlinfo->mouse_face_window)
33748 && XWINDOW (hlinfo->mouse_face_window) == w))
33749 return false;
33750 if (vpos < hlinfo->mouse_face_beg_row
33751 || vpos > hlinfo->mouse_face_end_row)
33752 return false;
33753 if (vpos > hlinfo->mouse_face_beg_row
33754 && vpos < hlinfo->mouse_face_end_row)
33755 return true;
33756
33757 if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
33758 {
33759 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
33760 {
33761 if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col)
33762 return true;
33763 }
33764 else if ((vpos == hlinfo->mouse_face_beg_row
33765 && hpos >= hlinfo->mouse_face_beg_col)
33766 || (vpos == hlinfo->mouse_face_end_row
33767 && hpos < hlinfo->mouse_face_end_col))
33768 return true;
33769 }
33770 else
33771 {
33772 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
33773 {
33774 if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col)
33775 return true;
33776 }
33777 else if ((vpos == hlinfo->mouse_face_beg_row
33778 && hpos <= hlinfo->mouse_face_beg_col)
33779 || (vpos == hlinfo->mouse_face_end_row
33780 && hpos > hlinfo->mouse_face_end_col))
33781 return true;
33782 }
33783 return false;
33784 }
33785
33786
33787
33788
33789
33790 bool
33791 cursor_in_mouse_face_p (struct window *w)
33792 {
33793 int vpos = w->phys_cursor.vpos;
33794
33795
33796
33797 if (!(0 <= vpos && vpos < w->current_matrix->nrows))
33798 return false;
33799
33800 int hpos = w->phys_cursor.hpos;
33801 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
33802
33803
33804
33805
33806 if (!row->reversed_p && hpos < 0)
33807 hpos = 0;
33808 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33809 hpos = row->used[TEXT_AREA] - 1;
33810
33811 return coords_in_mouse_face_p (w, hpos, vpos);
33812 }
33813
33814
33815
33816
33817
33818
33819
33820
33821
33822 static void
33823 rows_from_pos_range (struct window *w,
33824 ptrdiff_t start_charpos, ptrdiff_t end_charpos,
33825 Lisp_Object disp_string,
33826 struct glyph_row **start, struct glyph_row **end)
33827 {
33828 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
33829 int last_y = window_text_bottom_y (w);
33830 struct glyph_row *row;
33831
33832 *start = NULL;
33833 *end = NULL;
33834
33835 while (!first->enabled_p
33836 && first < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w))
33837 first++;
33838
33839
33840 for (row = first;
33841 row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y;
33842 row++)
33843 {
33844
33845
33846
33847 if (! ((start_charpos < MATRIX_ROW_START_CHARPOS (row)
33848 && end_charpos < MATRIX_ROW_START_CHARPOS (row))
33849
33850
33851
33852
33853 || ((start_charpos > MATRIX_ROW_END_CHARPOS (row)
33854 || (start_charpos == MATRIX_ROW_END_CHARPOS (row)
33855 && !row->ends_at_zv_p
33856 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
33857 && (end_charpos > MATRIX_ROW_END_CHARPOS (row)
33858 || (end_charpos == MATRIX_ROW_END_CHARPOS (row)
33859 && !row->ends_at_zv_p
33860 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))))))
33861 {
33862
33863
33864
33865
33866
33867
33868
33869
33870
33871
33872 struct glyph *g = row->glyphs[TEXT_AREA];
33873 struct glyph *e = g + row->used[TEXT_AREA];
33874
33875 while (g < e)
33876 {
33877 if (((BUFFERP (g->object) || NILP (g->object))
33878 && start_charpos <= g->charpos && g->charpos < end_charpos)
33879
33880
33881 || EQ (g->object, disp_string))
33882 *start = row;
33883 g++;
33884 }
33885 if (*start)
33886 break;
33887 }
33888 }
33889
33890
33891 if (!*start
33892
33893
33894 && !(row->enabled_p
33895 && row->y < last_y && MATRIX_ROW_BOTTOM_Y (row) > last_y))
33896 row = first;
33897 for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++)
33898 {
33899 struct glyph_row *next = row + 1;
33900 ptrdiff_t next_start = MATRIX_ROW_START_CHARPOS (next);
33901
33902 if (!next->enabled_p
33903 || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)
33904
33905
33906
33907 || (start_charpos < next_start
33908 && end_charpos < next_start)
33909 || ((start_charpos > MATRIX_ROW_END_CHARPOS (next)
33910 || (start_charpos == MATRIX_ROW_END_CHARPOS (next)
33911 && !next->ends_at_zv_p
33912 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))
33913 && (end_charpos > MATRIX_ROW_END_CHARPOS (next)
33914 || (end_charpos == MATRIX_ROW_END_CHARPOS (next)
33915 && !next->ends_at_zv_p
33916 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))))
33917 {
33918 *end = row;
33919 break;
33920 }
33921 else
33922 {
33923
33924
33925
33926 struct glyph *g = next->glyphs[TEXT_AREA];
33927 struct glyph *s = g;
33928 struct glyph *e = g + next->used[TEXT_AREA];
33929
33930 while (g < e)
33931 {
33932 if (((BUFFERP (g->object) || NILP (g->object))
33933 && ((start_charpos <= g->charpos && g->charpos < end_charpos)
33934
33935
33936
33937
33938
33939 || (((!next->reversed_p && g == s)
33940 || (next->reversed_p && g == e - 1))
33941 && (g->charpos == end_charpos
33942
33943
33944 || (g->charpos == -1
33945 && !row->ends_at_zv_p
33946 && next_start == end_charpos)))))
33947
33948
33949 || EQ (g->object, disp_string))
33950 break;
33951 g++;
33952 }
33953 if (g == e)
33954 {
33955 *end = row;
33956 break;
33957 }
33958
33959
33960 else if (next->ends_at_zv_p)
33961 {
33962 *end = next;
33963 break;
33964 }
33965 }
33966 }
33967 }
33968
33969
33970
33971
33972
33973
33974
33975
33976
33977
33978 static void
33979 mouse_face_from_buffer_pos (Lisp_Object window,
33980 Mouse_HLInfo *hlinfo,
33981 ptrdiff_t mouse_charpos,
33982 ptrdiff_t start_charpos,
33983 ptrdiff_t end_charpos,
33984 Lisp_Object before_string,
33985 Lisp_Object after_string,
33986 Lisp_Object disp_string)
33987 {
33988 struct window *w = XWINDOW (window);
33989 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
33990 struct glyph_row *r1, *r2;
33991 struct glyph *glyph, *end;
33992 ptrdiff_t ignore, pos;
33993 int x;
33994
33995 eassert (NILP (disp_string) || STRINGP (disp_string));
33996 eassert (NILP (before_string) || STRINGP (before_string));
33997 eassert (NILP (after_string) || STRINGP (after_string));
33998
33999
34000 rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
34001 if (r1 == NULL)
34002 r1 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34003
34004
34005 if (!NILP (before_string) || !NILP (disp_string))
34006 {
34007 struct glyph_row *prev;
34008 while ((prev = r1 - 1, prev >= first)
34009 && MATRIX_ROW_END_CHARPOS (prev) == start_charpos
34010 && prev->used[TEXT_AREA] > 0)
34011 {
34012 struct glyph *beg = prev->glyphs[TEXT_AREA];
34013 glyph = beg + prev->used[TEXT_AREA];
34014 while (--glyph >= beg && NILP (glyph->object));
34015 if (glyph < beg
34016 || !(EQ (glyph->object, before_string)
34017 || EQ (glyph->object, disp_string)))
34018 break;
34019 r1 = prev;
34020 }
34021 }
34022 if (r2 == NULL)
34023 {
34024 r2 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34025 hlinfo->mouse_face_past_end = true;
34026 }
34027 else if (!NILP (after_string))
34028 {
34029
34030 struct glyph_row *next;
34031 struct glyph_row *last
34032 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34033
34034 for (next = r2 + 1;
34035 next <= last
34036 && next->used[TEXT_AREA] > 0
34037 && EQ (next->glyphs[TEXT_AREA]->object, after_string);
34038 ++next)
34039 r2 = next;
34040 }
34041
34042
34043
34044
34045
34046 if (r1->y > r2->y)
34047 {
34048 struct glyph_row *tem = r2;
34049
34050 r2 = r1;
34051 r1 = tem;
34052 }
34053
34054 hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
34055 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
34056
34057
34058
34059
34060
34061
34062
34063
34064
34065
34066
34067 if (!r1->reversed_p)
34068 {
34069
34070
34071 glyph = r1->glyphs[TEXT_AREA];
34072 end = glyph + r1->used[TEXT_AREA];
34073 x = r1->x;
34074
34075
34076 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34077 for (; glyph < end
34078 && NILP (glyph->object)
34079 && glyph->charpos < 0;
34080 ++glyph)
34081 x += glyph->pixel_width;
34082
34083
34084
34085
34086 for (; glyph < end
34087 && !NILP (glyph->object)
34088 && !EQ (glyph->object, disp_string)
34089 && !(BUFFERP (glyph->object)
34090 && (glyph->charpos >= start_charpos
34091 && glyph->charpos < end_charpos));
34092 ++glyph)
34093 {
34094
34095
34096
34097 if (EQ (glyph->object, before_string))
34098 {
34099 pos = string_buffer_position (before_string,
34100 start_charpos);
34101
34102
34103 if (!pos || (pos >= start_charpos && pos < end_charpos))
34104 break;
34105 }
34106 else if (EQ (glyph->object, after_string))
34107 {
34108 pos = string_buffer_position (after_string, end_charpos);
34109 if (!pos || (pos >= start_charpos && pos < end_charpos))
34110 break;
34111 }
34112 x += glyph->pixel_width;
34113 }
34114 hlinfo->mouse_face_beg_x = x;
34115 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34116 }
34117 else
34118 {
34119
34120
34121 struct glyph *g;
34122
34123 end = r1->glyphs[TEXT_AREA] - 1;
34124 glyph = end + r1->used[TEXT_AREA];
34125
34126
34127 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34128 for (; glyph > end
34129 && NILP (glyph->object)
34130 && glyph->charpos < 0;
34131 --glyph)
34132 ;
34133
34134
34135
34136
34137 for (; glyph > end
34138 && !NILP (glyph->object)
34139 && !EQ (glyph->object, disp_string)
34140 && !(BUFFERP (glyph->object)
34141 && (glyph->charpos >= start_charpos
34142 && glyph->charpos < end_charpos));
34143 --glyph)
34144 {
34145
34146
34147
34148 if (EQ (glyph->object, before_string))
34149 {
34150 pos = string_buffer_position (before_string, start_charpos);
34151
34152
34153 if (!pos || (pos >= start_charpos && pos < end_charpos))
34154 break;
34155 }
34156 else if (EQ (glyph->object, after_string))
34157 {
34158 pos = string_buffer_position (after_string, end_charpos);
34159 if (!pos || (pos >= start_charpos && pos < end_charpos))
34160 break;
34161 }
34162 }
34163
34164 glyph++;
34165 for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++)
34166 x += g->pixel_width;
34167 hlinfo->mouse_face_beg_x = x;
34168 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34169 }
34170
34171
34172
34173
34174 if (r2 != r1)
34175 {
34176 if (!r2->reversed_p)
34177 {
34178 glyph = r2->glyphs[TEXT_AREA];
34179 end = glyph + r2->used[TEXT_AREA];
34180 x = r2->x;
34181 }
34182 else
34183 {
34184 end = r2->glyphs[TEXT_AREA] - 1;
34185 glyph = end + r2->used[TEXT_AREA];
34186 }
34187 }
34188
34189 if (!r2->reversed_p)
34190 {
34191
34192
34193
34194 while (end > glyph
34195 && NILP ((end - 1)->object))
34196 --end;
34197
34198
34199
34200
34201 for (--end;
34202 end > glyph
34203 && !NILP (end->object)
34204 && !EQ (end->object, disp_string)
34205 && !(BUFFERP (end->object)
34206 && (end->charpos >= start_charpos
34207 && end->charpos < end_charpos));
34208 --end)
34209 {
34210
34211
34212
34213 if (EQ (end->object, before_string))
34214 {
34215 pos = string_buffer_position (before_string, start_charpos);
34216 if (!pos || (pos >= start_charpos && pos < end_charpos))
34217 break;
34218 }
34219 else if (EQ (end->object, after_string))
34220 {
34221 pos = string_buffer_position (after_string, end_charpos);
34222 if (!pos || (pos >= start_charpos && pos < end_charpos))
34223 break;
34224 }
34225 }
34226
34227 for (; glyph <= end; ++glyph)
34228 x += glyph->pixel_width;
34229
34230 hlinfo->mouse_face_end_x = x;
34231 hlinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA];
34232 }
34233 else
34234 {
34235
34236
34237
34238 x = r2->x;
34239 end++;
34240 while (end < glyph
34241 && NILP (end->object))
34242 {
34243 x += end->pixel_width;
34244 ++end;
34245 }
34246
34247
34248
34249
34250 for ( ;
34251 end < glyph
34252 && !NILP (end->object)
34253 && !EQ (end->object, disp_string)
34254 && !(BUFFERP (end->object)
34255 && (end->charpos >= start_charpos
34256 && end->charpos < end_charpos));
34257 ++end)
34258 {
34259
34260
34261
34262 if (EQ (end->object, before_string))
34263 {
34264 pos = string_buffer_position (before_string, start_charpos);
34265 if (!pos || (pos >= start_charpos && pos < end_charpos))
34266 break;
34267 }
34268 else if (EQ (end->object, after_string))
34269 {
34270 pos = string_buffer_position (after_string, end_charpos);
34271 if (!pos || (pos >= start_charpos && pos < end_charpos))
34272 break;
34273 }
34274 x += end->pixel_width;
34275 }
34276
34277
34278
34279
34280
34281 if (end == glyph
34282 && BUFFERP (end->object)
34283 && (end->charpos < start_charpos
34284 || end->charpos >= end_charpos))
34285 {
34286 x += end->pixel_width;
34287 ++end;
34288 }
34289 hlinfo->mouse_face_end_x = x;
34290 hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
34291 }
34292
34293 hlinfo->mouse_face_window = window;
34294 hlinfo->mouse_face_face_id
34295 = face_at_buffer_position (w, mouse_charpos, &ignore,
34296 mouse_charpos + 1,
34297 !hlinfo->mouse_face_hidden, -1, 0);
34298 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
34299 }
34300
34301
34302
34303
34304
34305 #if false
34306
34307
34308
34309
34310
34311
34312
34313
34314
34315
34316
34317
34318
34319
34320
34321
34322 static bool
34323 fast_find_string_pos (struct window *w, ptrdiff_t pos, Lisp_Object object,
34324 int *hpos, int *vpos, int *x, int *y, bool right_p)
34325 {
34326 int yb = window_text_bottom_y (w);
34327 struct glyph_row *r;
34328 struct glyph *best_glyph = NULL;
34329 struct glyph_row *best_row = NULL;
34330 int best_x = 0;
34331
34332 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34333 r->enabled_p && r->y < yb;
34334 ++r)
34335 {
34336 struct glyph *g = r->glyphs[TEXT_AREA];
34337 struct glyph *e = g + r->used[TEXT_AREA];
34338 int gx;
34339
34340 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34341 if (EQ (g->object, object))
34342 {
34343 if (g->charpos == pos)
34344 {
34345 best_glyph = g;
34346 best_x = gx;
34347 best_row = r;
34348 goto found;
34349 }
34350 else if (best_glyph == NULL
34351 || ((eabs (g->charpos - pos)
34352 < eabs (best_glyph->charpos - pos))
34353 && (right_p
34354 ? g->charpos < pos
34355 : g->charpos > pos)))
34356 {
34357 best_glyph = g;
34358 best_x = gx;
34359 best_row = r;
34360 }
34361 }
34362 }
34363
34364 found:
34365
34366 if (best_glyph)
34367 {
34368 *x = best_x;
34369 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
34370
34371 if (right_p)
34372 {
34373 *x += best_glyph->pixel_width;
34374 ++*hpos;
34375 }
34376
34377 *y = best_row->y;
34378 *vpos = MATRIX_ROW_VPOS (best_row, w->current_matrix);
34379 }
34380
34381 return best_glyph != NULL;
34382 }
34383 #endif
34384
34385
34386
34387
34388
34389
34390 static void
34391 mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo,
34392 Lisp_Object object,
34393 ptrdiff_t startpos, ptrdiff_t endpos)
34394 {
34395 int yb = window_text_bottom_y (w);
34396 struct glyph_row *r;
34397 struct glyph *g, *e;
34398 int gx;
34399 bool found = false;
34400
34401
34402
34403
34404 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34405 r->enabled_p && r->y < yb;
34406 ++r)
34407 {
34408 if (!r->reversed_p)
34409 {
34410 g = r->glyphs[TEXT_AREA];
34411 e = g + r->used[TEXT_AREA];
34412 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34413 if (EQ (g->object, object)
34414 && startpos <= g->charpos && g->charpos < endpos)
34415 {
34416 hlinfo->mouse_face_beg_row
34417 = MATRIX_ROW_VPOS (r, w->current_matrix);
34418 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34419 hlinfo->mouse_face_beg_x = gx;
34420 found = true;
34421 break;
34422 }
34423 }
34424 else
34425 {
34426 struct glyph *g1;
34427
34428 e = r->glyphs[TEXT_AREA];
34429 g = e + r->used[TEXT_AREA];
34430 for ( ; g > e; --g)
34431 if (EQ ((g-1)->object, object)
34432 && startpos <= (g-1)->charpos && (g-1)->charpos < endpos)
34433 {
34434 hlinfo->mouse_face_beg_row
34435 = MATRIX_ROW_VPOS (r, w->current_matrix);
34436 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34437 for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
34438 gx += g1->pixel_width;
34439 hlinfo->mouse_face_beg_x = gx;
34440 found = true;
34441 break;
34442 }
34443 }
34444 if (found)
34445 break;
34446 }
34447
34448 if (!found)
34449 return;
34450
34451
34452
34453 for (++r; r->enabled_p && r->y < yb; ++r)
34454 {
34455 g = r->glyphs[TEXT_AREA];
34456 e = g + r->used[TEXT_AREA];
34457 found = false;
34458 for ( ; g < e; ++g)
34459 if (EQ (g->object, object)
34460 && startpos <= g->charpos && g->charpos < endpos)
34461 {
34462 found = true;
34463 break;
34464 }
34465 if (!found)
34466 break;
34467 }
34468
34469
34470 r--;
34471
34472
34473 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r, w->current_matrix);
34474
34475
34476
34477 if (!r->reversed_p)
34478 {
34479 g = r->glyphs[TEXT_AREA];
34480 e = g + r->used[TEXT_AREA];
34481 for ( ; e > g; --e)
34482 if (EQ ((e-1)->object, object)
34483 && startpos <= (e-1)->charpos && (e-1)->charpos < endpos)
34484 break;
34485 hlinfo->mouse_face_end_col = e - g;
34486
34487 for (gx = r->x; g < e; ++g)
34488 gx += g->pixel_width;
34489 hlinfo->mouse_face_end_x = gx;
34490 }
34491 else
34492 {
34493 e = r->glyphs[TEXT_AREA];
34494 g = e + r->used[TEXT_AREA];
34495 for (gx = r->x ; e < g; ++e)
34496 {
34497 if (EQ (e->object, object)
34498 && startpos <= e->charpos && e->charpos < endpos)
34499 break;
34500 gx += e->pixel_width;
34501 }
34502 hlinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA];
34503 hlinfo->mouse_face_end_x = gx;
34504 }
34505 }
34506
34507 #ifdef HAVE_WINDOW_SYSTEM
34508
34509
34510
34511 static bool
34512 on_hot_spot_p (Lisp_Object hot_spot, int x, int y)
34513 {
34514 if (!CONSP (hot_spot))
34515 return false;
34516
34517 if (EQ (XCAR (hot_spot), Qrect))
34518 {
34519
34520 Lisp_Object rect = XCDR (hot_spot);
34521 Lisp_Object tem;
34522 if (!CONSP (rect))
34523 return false;
34524 if (!CONSP (XCAR (rect)))
34525 return false;
34526 if (!CONSP (XCDR (rect)))
34527 return false;
34528 if (!(tem = XCAR (XCAR (rect)), FIXNUMP (tem) && x >= XFIXNUM (tem)))
34529 return false;
34530 if (!(tem = XCDR (XCAR (rect)), FIXNUMP (tem) && y >= XFIXNUM (tem)))
34531 return false;
34532 if (!(tem = XCAR (XCDR (rect)), FIXNUMP (tem) && x <= XFIXNUM (tem)))
34533 return false;
34534 if (!(tem = XCDR (XCDR (rect)), FIXNUMP (tem) && y <= XFIXNUM (tem)))
34535 return false;
34536 return true;
34537 }
34538 else if (EQ (XCAR (hot_spot), Qcircle))
34539 {
34540
34541 Lisp_Object circ = XCDR (hot_spot);
34542 Lisp_Object lr, lx0, ly0;
34543 if (CONSP (circ)
34544 && CONSP (XCAR (circ))
34545 && (lr = XCDR (circ), NUMBERP (lr))
34546 && (lx0 = XCAR (XCAR (circ)), FIXNUMP (lx0))
34547 && (ly0 = XCDR (XCAR (circ)), FIXNUMP (ly0)))
34548 {
34549 double r = XFLOATINT (lr);
34550 double dx = XFIXNUM (lx0) - x;
34551 double dy = XFIXNUM (ly0) - y;
34552 return (dx * dx + dy * dy <= r * r);
34553 }
34554 }
34555 else if (EQ (XCAR (hot_spot), Qpoly))
34556 {
34557
34558 if (VECTORP (XCDR (hot_spot)))
34559 {
34560 struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
34561 Lisp_Object *poly = v->contents;
34562 ptrdiff_t n = v->header.size;
34563 ptrdiff_t i;
34564 bool inside = false;
34565 Lisp_Object lx, ly;
34566 int x0, y0;
34567
34568
34569 if (n < 6 || n & 1)
34570 return false;
34571
34572
34573
34574
34575
34576 if ((lx = poly[n-2], !FIXNUMP (lx))
34577 || (ly = poly[n-1], !FIXNUMP (lx)))
34578 return false;
34579 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34580 for (i = 0; i < n; i += 2)
34581 {
34582 int x1 = x0, y1 = y0;
34583 if ((lx = poly[i], !FIXNUMP (lx))
34584 || (ly = poly[i+1], !FIXNUMP (ly)))
34585 return false;
34586 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34587
34588
34589 if (x0 >= x)
34590 {
34591 if (x1 >= x)
34592 continue;
34593 }
34594 else if (x1 < x)
34595 continue;
34596 if (y > y0 && y > y1)
34597 continue;
34598 if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0))
34599 inside = !inside;
34600 }
34601 return inside;
34602 }
34603 }
34604 return false;
34605 }
34606
34607 Lisp_Object
34608 find_hot_spot (Lisp_Object map, int x, int y)
34609 {
34610 while (CONSP (map))
34611 {
34612 if (CONSP (XCAR (map))
34613 && on_hot_spot_p (XCAR (XCAR (map)), x, y))
34614 return XCAR (map);
34615 map = XCDR (map);
34616 }
34617
34618 return Qnil;
34619 }
34620
34621 DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
34622 3, 3, 0,
34623 doc:
34624
34625
34626
34627
34628
34629
34630
34631
34632 )
34633 (Lisp_Object map, Lisp_Object x, Lisp_Object y)
34634 {
34635 if (NILP (map))
34636 return Qnil;
34637
34638 CHECK_FIXNUM (x);
34639 CHECK_FIXNUM (y);
34640
34641 return find_hot_spot (map,
34642 clip_to_bounds (INT_MIN, XFIXNUM (x), INT_MAX),
34643 clip_to_bounds (INT_MIN, XFIXNUM (y), INT_MAX));
34644 }
34645 #endif
34646
34647
34648
34649 static void
34650 define_frame_cursor1 (struct frame *f, Emacs_Cursor cursor, Lisp_Object pointer)
34651 {
34652 #ifdef HAVE_WINDOW_SYSTEM
34653 if (!FRAME_WINDOW_P (f))
34654 return;
34655
34656
34657 if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping)
34658 || EQ (track_mouse, Qdrag_source))
34659 return;
34660
34661 if (!NILP (pointer))
34662 {
34663 if (EQ (pointer, Qarrow))
34664 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34665 else if (EQ (pointer, Qhand))
34666 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
34667 else if (EQ (pointer, Qtext))
34668 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
34669 else if (EQ (pointer, intern ("hdrag")))
34670 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
34671 else if (EQ (pointer, intern ("nhdrag")))
34672 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34673 # ifdef HAVE_X_WINDOWS
34674 else if (EQ (pointer, intern ("vdrag")))
34675 cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
34676 # endif
34677 else if (EQ (pointer, intern ("hourglass")))
34678 cursor = FRAME_OUTPUT_DATA (f)->hourglass_cursor;
34679 else if (EQ (pointer, Qmodeline))
34680 cursor = FRAME_OUTPUT_DATA (f)->modeline_cursor;
34681 else
34682 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34683 }
34684
34685 if (cursor != No_Cursor)
34686 FRAME_RIF (f)->define_frame_cursor (f, cursor);
34687 #endif
34688 }
34689
34690
34691
34692
34693
34694
34695
34696 static void
34697 note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
34698 enum window_part area)
34699 {
34700 struct window *w = XWINDOW (window);
34701 struct frame *f = XFRAME (w->frame);
34702 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
34703 Emacs_Cursor cursor = No_Cursor;
34704 Lisp_Object pointer = Qnil;
34705 int dx, dy, width, height;
34706 ptrdiff_t charpos;
34707 Lisp_Object string, object = Qnil;
34708 Lisp_Object pos UNINIT;
34709 Lisp_Object mouse_face;
34710 int original_x_pixel = x;
34711 struct glyph * glyph = NULL, * row_start_glyph = NULL;
34712 struct glyph_row *row UNINIT;
34713
34714 if (area == ON_MODE_LINE || area == ON_HEADER_LINE || area == ON_TAB_LINE)
34715 {
34716 int x0;
34717 struct glyph *end;
34718
34719
34720
34721 string = mode_line_string (w, area, &x, &y, &charpos,
34722 &object, &dx, &dy, &width, &height);
34723
34724 row = (area == ON_MODE_LINE
34725 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
34726 : (area == ON_TAB_LINE
34727 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
34728 : MATRIX_HEADER_LINE_ROW (w->current_matrix)));
34729
34730
34731 if (row->mode_line_p && row->enabled_p)
34732 {
34733 glyph = row_start_glyph = row->glyphs[TEXT_AREA];
34734 end = glyph + row->used[TEXT_AREA];
34735
34736 for (x0 = original_x_pixel;
34737 glyph < end && x0 >= glyph->pixel_width;
34738 ++glyph)
34739 x0 -= glyph->pixel_width;
34740
34741 if (glyph >= end)
34742 glyph = NULL;
34743 }
34744 }
34745 else
34746 {
34747 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
34748
34749
34750 string = marginal_area_string (w, area, &x, &y, &charpos,
34751 &object, &dx, &dy, &width, &height);
34752 }
34753
34754 Lisp_Object help = Qnil;
34755
34756 #ifdef HAVE_WINDOW_SYSTEM
34757 if (IMAGEP (object))
34758 {
34759 Lisp_Object image_map, hotspot;
34760 if ((image_map = plist_get (XCDR (object), QCmap),
34761 !NILP (image_map))
34762 && (hotspot = find_hot_spot (image_map, dx, dy),
34763 CONSP (hotspot))
34764 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
34765 {
34766 Lisp_Object plist;
34767
34768
34769
34770
34771 hotspot = XCDR (hotspot);
34772 if (CONSP (hotspot)
34773 && (plist = XCAR (hotspot), CONSP (plist)))
34774 {
34775 pointer = plist_get (plist, Qpointer);
34776 if (NILP (pointer))
34777 pointer = Qhand;
34778 help = plist_get (plist, Qhelp_echo);
34779 if (!NILP (help))
34780 {
34781 help_echo_string = help;
34782 XSETWINDOW (help_echo_window, w);
34783 help_echo_object = w->contents;
34784 help_echo_pos = charpos;
34785 }
34786 }
34787 }
34788 if (NILP (pointer))
34789 pointer = plist_get (XCDR (object), QCpointer);
34790 }
34791 #endif
34792
34793
34794
34795
34796 if (STRINGP (string))
34797 pos = make_fixnum (min (charpos, SCHARS (string) - 1));
34798
34799
34800
34801
34802
34803 if (STRINGP (string) || area == ON_MODE_LINE || area == ON_HEADER_LINE
34804 || area == ON_TAB_LINE)
34805 {
34806
34807
34808 if (NILP (help))
34809 {
34810 if (STRINGP (string))
34811 help = Fget_text_property (pos, Qhelp_echo, string);
34812
34813 if (!NILP (help))
34814 {
34815 help_echo_string = help;
34816 XSETWINDOW (help_echo_window, w);
34817 help_echo_object = string;
34818 help_echo_pos = charpos;
34819 }
34820 else if (area == ON_MODE_LINE
34821 && !NILP (w->mode_line_help_echo))
34822 {
34823 help_echo_string = w->mode_line_help_echo;
34824 XSETWINDOW (help_echo_window, w);
34825 help_echo_object = Qnil;
34826 help_echo_pos = -1;
34827 }
34828 }
34829
34830 #ifdef HAVE_WINDOW_SYSTEM
34831
34832 if (FRAME_WINDOW_P (f))
34833 {
34834 bool draggable = (! WINDOW_BOTTOMMOST_P (w)
34835 || minibuf_level
34836 || NILP (Vresize_mini_windows));
34837
34838 if (STRINGP (string))
34839 {
34840 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34841
34842 if (NILP (pointer))
34843 pointer = Fget_text_property (pos, Qpointer, string);
34844
34845
34846 if (NILP (pointer)
34847 && (area == ON_MODE_LINE || area == ON_HEADER_LINE
34848 || area == ON_TAB_LINE))
34849 {
34850 Lisp_Object map;
34851
34852 map = Fget_text_property (pos, Qlocal_map, string);
34853 if (!KEYMAPP (map))
34854 map = Fget_text_property (pos, Qkeymap, string);
34855 if (!KEYMAPP (map) && draggable && area == ON_MODE_LINE)
34856 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34857 }
34858 }
34859 else if (draggable && area == ON_MODE_LINE)
34860 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34861 else if ((area == ON_MODE_LINE
34862 && WINDOW_BOTTOMMOST_P (w)
34863 && !FRAME_HAS_MINIBUF_P (f)
34864 && !NILP (Fframe_parameter
34865 (w->frame, Qdrag_with_mode_line)))
34866 || (((area == ON_HEADER_LINE
34867 && !NILP (Fframe_parameter
34868 (w->frame, Qdrag_with_header_line)))
34869 || (area == ON_TAB_LINE
34870 && !NILP (Fframe_parameter
34871 (w->frame, Qdrag_with_tab_line))))
34872 && WINDOW_TOPMOST_P (w)))
34873 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
34874 else
34875 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34876 }
34877 #endif
34878 }
34879
34880
34881 bool mouse_face_shown = false;
34882
34883 if (STRINGP (string))
34884 {
34885 mouse_face = Fget_text_property (pos, Qmouse_face, string);
34886 if (!NILP (Vmouse_highlight) && !NILP (mouse_face)
34887 && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)
34888 || (area == ON_TAB_LINE))
34889 && glyph)
34890 {
34891 Lisp_Object b, e;
34892
34893 struct glyph * tmp_glyph;
34894
34895 int gpos;
34896 int gseq_length;
34897 int total_pixel_width;
34898 ptrdiff_t begpos, endpos, ignore;
34899
34900 int vpos, hpos;
34901
34902 b = Fprevious_single_property_change (make_fixnum (charpos + 1),
34903 Qmouse_face, string, Qnil);
34904 if (NILP (b))
34905 begpos = 0;
34906 else
34907 begpos = XFIXNUM (b);
34908
34909 e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil);
34910 if (NILP (e))
34911 endpos = SCHARS (string);
34912 else
34913 endpos = XFIXNUM (e);
34914
34915
34916
34917
34918
34919
34920
34921
34922
34923
34924
34925 tmp_glyph = row_start_glyph;
34926 while (tmp_glyph < glyph
34927 && (!(EQ (tmp_glyph->object, glyph->object)
34928 && begpos <= tmp_glyph->charpos
34929 && tmp_glyph->charpos < endpos)))
34930 tmp_glyph++;
34931 gpos = glyph - tmp_glyph;
34932
34933
34934
34935
34936
34937
34938 for (tmp_glyph = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
34939 tmp_glyph > glyph
34940 && (!(EQ (tmp_glyph->object, glyph->object)
34941 && begpos <= tmp_glyph->charpos
34942 && tmp_glyph->charpos < endpos));
34943 tmp_glyph--)
34944 ;
34945 gseq_length = gpos + (tmp_glyph - glyph) + 1;
34946
34947
34948
34949 total_pixel_width = 0;
34950 for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++)
34951 total_pixel_width += tmp_glyph->pixel_width;
34952
34953
34954
34955
34956 hpos = x - gpos;
34957 vpos = (area == ON_MODE_LINE
34958 ? (w->current_matrix)->nrows - 1
34959 : (area == ON_TAB_LINE
34960 ? 0
34961 : (w->current_matrix->tab_line_p
34962 ? 1
34963 : 0)));
34964
34965
34966
34967 if ( EQ (window, hlinfo->mouse_face_window)
34968 && (!row->reversed_p
34969 ? (hlinfo->mouse_face_beg_col <= hpos
34970 && hpos < hlinfo->mouse_face_end_col)
34971
34972 : (hlinfo->mouse_face_end_col <= hpos
34973 && hpos < hlinfo->mouse_face_beg_col))
34974 && hlinfo->mouse_face_beg_row == vpos )
34975 return;
34976
34977 if (clear_mouse_face (hlinfo))
34978 cursor = No_Cursor;
34979
34980 if (!row->reversed_p)
34981 {
34982 hlinfo->mouse_face_beg_col = hpos;
34983 hlinfo->mouse_face_beg_x = original_x_pixel
34984 - (total_pixel_width + dx);
34985 hlinfo->mouse_face_end_col = hpos + gseq_length;
34986 hlinfo->mouse_face_end_x = 0;
34987 }
34988 else
34989 {
34990
34991
34992 hlinfo->mouse_face_end_col = hpos;
34993 hlinfo->mouse_face_end_x = original_x_pixel
34994 - (total_pixel_width + dx);
34995 hlinfo->mouse_face_beg_col = hpos + gseq_length;
34996 hlinfo->mouse_face_beg_x = 0;
34997 }
34998
34999 hlinfo->mouse_face_beg_row = vpos;
35000 hlinfo->mouse_face_end_row = hlinfo->mouse_face_beg_row;
35001 hlinfo->mouse_face_past_end = false;
35002 hlinfo->mouse_face_window = window;
35003
35004 hlinfo->mouse_face_face_id =
35005 face_at_string_position (w, string, charpos, 0, &ignore,
35006 glyph->face_id, true, 0);
35007
35008 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35009 mouse_face_shown = true;
35010
35011 if (NILP (pointer))
35012 pointer = Qhand;
35013 }
35014 }
35015
35016
35017
35018 if ((area == ON_MODE_LINE || area == ON_HEADER_LINE
35019 || area == ON_TAB_LINE) && !mouse_face_shown)
35020 clear_mouse_face (hlinfo);
35021
35022 define_frame_cursor1 (f, cursor, pointer);
35023 }
35024
35025
35026
35027
35028
35029
35030
35031
35032
35033
35034 void
35035 note_mouse_highlight (struct frame *f, int x, int y)
35036 {
35037 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35038 enum window_part part = ON_NOTHING;
35039 Lisp_Object window;
35040 struct window *w;
35041 Emacs_Cursor cursor = No_Cursor;
35042 Lisp_Object pointer = Qnil;
35043 struct buffer *b;
35044
35045
35046 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS) || defined (MSDOS)
35047 if (popup_activated ())
35048 return;
35049 #endif
35050
35051 #if defined (HAVE_HAIKU)
35052 if (popup_activated_p)
35053 return;
35054 #endif
35055
35056 if (!f->glyphs_initialized_p
35057 || f->pointer_invisible)
35058 return;
35059
35060 hlinfo->mouse_face_mouse_x = x;
35061 hlinfo->mouse_face_mouse_y = y;
35062 hlinfo->mouse_face_mouse_frame = f;
35063
35064 if (hlinfo->mouse_face_defer)
35065 return;
35066
35067
35068 window = window_from_coordinates (f, x, y, &part, true, true);
35069
35070
35071 if (! EQ (window, hlinfo->mouse_face_window)
35072
35073 || (!NILP (hlinfo->mouse_face_window)
35074 && !NILP (window)
35075 && part != ON_TEXT
35076 && part != ON_MODE_LINE
35077 && part != ON_HEADER_LINE
35078 && part != ON_TAB_LINE))
35079 clear_mouse_face (hlinfo);
35080
35081
35082 help_echo_string = Qnil;
35083
35084
35085 if (!FRAME_WINDOW_P (f)
35086 && (y >= FRAME_MENU_BAR_LINES (f)
35087 && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)))
35088 {
35089 int prop_idx;
35090 bool ignore;
35091 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore);
35092
35093 if (!NILP (caption))
35094 {
35095 help_echo_object = help_echo_window = Qnil;
35096 help_echo_pos = -1;
35097 help_echo_string = AREF (f->tab_bar_items,
35098 prop_idx * TAB_BAR_ITEM_NSLOTS
35099 + TAB_BAR_ITEM_HELP);
35100 if (NILP (help_echo_string))
35101 help_echo_string = caption;
35102 }
35103 }
35104
35105 #ifdef HAVE_WINDOW_SYSTEM
35106
35107
35108 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
35109 && !NILP (get_frame_param (f, Qdrag_internal_border)))
35110 {
35111 enum internal_border_part part = frame_internal_border_part (f, x, y);
35112
35113 switch (part)
35114 {
35115 case INTERNAL_BORDER_NONE:
35116 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35117
35118 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35119 break;
35120 case INTERNAL_BORDER_LEFT_EDGE:
35121 cursor = FRAME_OUTPUT_DATA (f)->left_edge_cursor;
35122 break;
35123 case INTERNAL_BORDER_TOP_LEFT_CORNER:
35124 cursor = FRAME_OUTPUT_DATA (f)->top_left_corner_cursor;
35125 break;
35126 case INTERNAL_BORDER_TOP_EDGE:
35127 cursor = FRAME_OUTPUT_DATA (f)->top_edge_cursor;
35128 break;
35129 case INTERNAL_BORDER_TOP_RIGHT_CORNER:
35130 cursor = FRAME_OUTPUT_DATA (f)->top_right_corner_cursor;
35131 break;
35132 case INTERNAL_BORDER_RIGHT_EDGE:
35133 cursor = FRAME_OUTPUT_DATA (f)->right_edge_cursor;
35134 break;
35135 case INTERNAL_BORDER_BOTTOM_RIGHT_CORNER:
35136 cursor = FRAME_OUTPUT_DATA (f)->bottom_right_corner_cursor;
35137 break;
35138 case INTERNAL_BORDER_BOTTOM_EDGE:
35139 cursor = FRAME_OUTPUT_DATA (f)->bottom_edge_cursor;
35140 break;
35141 case INTERNAL_BORDER_BOTTOM_LEFT_CORNER:
35142 cursor = FRAME_OUTPUT_DATA (f)->bottom_left_corner_cursor;
35143 break;
35144 default:
35145
35146 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35147 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35148 }
35149
35150 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35151 {
35152
35153 help_echo_string = build_string ("drag-mouse-1: resize frame");
35154 goto set_cursor;
35155 }
35156 }
35157 #endif
35158
35159
35160 if (!WINDOWP (window))
35161 return;
35162
35163
35164 w = XWINDOW (window);
35165 frame_to_window_pixel_xy (w, &x, &y);
35166
35167 #if defined (HAVE_WINDOW_SYSTEM)
35168
35169
35170 if (EQ (window, f->tab_bar_window))
35171 {
35172 note_tab_bar_highlight (f, x, y);
35173 if (tab_bar__dragging_in_progress)
35174 {
35175 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35176 goto set_cursor;
35177 }
35178 else
35179 return;
35180 }
35181 else
35182 {
35183
35184
35185
35186
35187 f->last_tab_bar_item = -1;
35188 }
35189 #endif
35190
35191 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
35192
35193
35194 if (EQ (window, f->tool_bar_window))
35195 {
35196 note_tool_bar_highlight (f, x, y);
35197 return;
35198 }
35199 #endif
35200
35201
35202 if (part == ON_MODE_LINE || part == ON_HEADER_LINE || part == ON_TAB_LINE
35203 || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35204 {
35205 note_mode_line_or_margin_highlight (window, x, y, part);
35206
35207 #ifdef HAVE_WINDOW_SYSTEM
35208 if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35209 {
35210 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35211
35212 goto set_cursor;
35213 }
35214 else
35215 #endif
35216 return;
35217 }
35218
35219 #ifdef HAVE_WINDOW_SYSTEM
35220 if (part == ON_VERTICAL_BORDER)
35221 {
35222 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35223 help_echo_string = build_string ("drag-mouse-1: resize");
35224 goto set_cursor;
35225 }
35226 else if (part == ON_RIGHT_DIVIDER)
35227 {
35228 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35229 help_echo_string = build_string ("drag-mouse-1: resize");
35230 goto set_cursor;
35231 }
35232 else if (part == ON_BOTTOM_DIVIDER)
35233 if (! WINDOW_BOTTOMMOST_P (w)
35234 || minibuf_level
35235 || NILP (Vresize_mini_windows))
35236 {
35237 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35238 help_echo_string = build_string ("drag-mouse-1: resize");
35239 goto set_cursor;
35240 }
35241 else
35242 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35243 else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
35244 || part == ON_VERTICAL_SCROLL_BAR
35245 || part == ON_HORIZONTAL_SCROLL_BAR)
35246 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35247 else
35248 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
35249 #endif
35250
35251
35252
35253 b = XBUFFER (w->contents);
35254 if (part == ON_TEXT && w->window_end_valid && !window_outdated (w))
35255 {
35256 int hpos, vpos, dx, dy, area = LAST_AREA;
35257 ptrdiff_t pos;
35258 struct glyph *glyph;
35259 Lisp_Object object;
35260 Lisp_Object mouse_face = Qnil, position;
35261 Lisp_Object *overlay_vec = NULL;
35262 ptrdiff_t i, noverlays;
35263 struct buffer *obuf;
35264 ptrdiff_t obegv, ozv;
35265 bool same_region;
35266
35267
35268 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area);
35269
35270 #ifdef HAVE_WINDOW_SYSTEM
35271
35272 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
35273 {
35274 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
35275 if (img != NULL && IMAGEP (img->spec))
35276 {
35277 Lisp_Object image_map, hotspot;
35278 if ((image_map = plist_get (XCDR (img->spec), QCmap),
35279 !NILP (image_map))
35280 && (hotspot = find_hot_spot (image_map,
35281 glyph->slice.img.x + dx,
35282 glyph->slice.img.y + dy),
35283 CONSP (hotspot))
35284 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35285 {
35286 Lisp_Object plist;
35287
35288
35289
35290
35291
35292 hotspot = XCDR (hotspot);
35293 if (CONSP (hotspot)
35294 && (plist = XCAR (hotspot), CONSP (plist)))
35295 {
35296 pointer = plist_get (plist, Qpointer);
35297 if (NILP (pointer))
35298 pointer = Qhand;
35299 help_echo_string = plist_get (plist, Qhelp_echo);
35300 if (!NILP (help_echo_string))
35301 {
35302 help_echo_window = window;
35303 help_echo_object = glyph->object;
35304 help_echo_pos = glyph->charpos;
35305 }
35306 }
35307 }
35308 if (NILP (pointer))
35309 pointer = plist_get (XCDR (img->spec), QCpointer);
35310 }
35311 }
35312 #endif
35313
35314
35315 if (glyph == NULL
35316 || area != TEXT_AREA
35317 || !MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->current_matrix, vpos))
35318
35319
35320
35321
35322
35323 || NILP (glyph->object)
35324
35325
35326
35327
35328 || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p
35329 && glyph == MATRIX_ROW_GLYPH_START (w->current_matrix, vpos)
35330 && glyph->type == STRETCH_GLYPH
35331 && glyph->avoid_cursor_p))
35332 {
35333 if (clear_mouse_face (hlinfo))
35334 cursor = No_Cursor;
35335 if (FRAME_WINDOW_P (f) && NILP (pointer))
35336 {
35337 #ifdef HAVE_WINDOW_SYSTEM
35338 if (area != TEXT_AREA)
35339 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35340 else
35341 pointer = Vvoid_text_area_pointer;
35342 #endif
35343 }
35344 goto set_cursor;
35345 }
35346
35347 pos = glyph->charpos;
35348 object = glyph->object;
35349 if (!STRINGP (object) && !BUFFERP (object))
35350 goto set_cursor;
35351
35352
35353 if (BUFFERP (object) && pos > BUF_Z (b))
35354 goto set_cursor;
35355
35356
35357
35358 obuf = current_buffer;
35359 current_buffer = b;
35360 obegv = BEGV;
35361 ozv = ZV;
35362 BEGV = BEG;
35363 ZV = Z;
35364
35365
35366 position = make_fixnum (pos);
35367
35368 USE_SAFE_ALLOCA;
35369
35370 if (BUFFERP (object))
35371 {
35372
35373 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL);
35374
35375 noverlays = sort_overlays (overlay_vec, noverlays, w);
35376 }
35377 else
35378 noverlays = 0;
35379
35380 if (NILP (Vmouse_highlight))
35381 {
35382 clear_mouse_face (hlinfo);
35383 goto check_help_echo;
35384 }
35385
35386 same_region = coords_in_mouse_face_p (w, hpos, vpos);
35387
35388 if (same_region)
35389 cursor = No_Cursor;
35390
35391
35392 if (! same_region
35393
35394
35395
35396
35397
35398 || (!hlinfo->mouse_face_hidden
35399 && OVERLAYP (hlinfo->mouse_face_overlay)
35400
35401 && OVERLAY_BUFFER (hlinfo->mouse_face_overlay)
35402 && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay)))
35403 {
35404
35405 Lisp_Object overlay = Qnil;
35406 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
35407 {
35408 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
35409 if (!NILP (mouse_face))
35410 overlay = overlay_vec[i];
35411 }
35412
35413
35414
35415 if (!NILP (overlay) && EQ (overlay, hlinfo->mouse_face_overlay))
35416 goto check_help_echo;
35417
35418
35419 if (clear_mouse_face (hlinfo))
35420 cursor = No_Cursor;
35421
35422
35423 hlinfo->mouse_face_overlay = overlay;
35424
35425
35426 if (NILP (overlay))
35427 mouse_face = Fget_text_property (position, Qmouse_face, object);
35428
35429
35430
35431 if (!NILP (mouse_face) && STRINGP (object))
35432 {
35433
35434
35435 Lisp_Object s, e;
35436 ptrdiff_t ignore;
35437
35438 s = Fprevious_single_property_change
35439 (make_fixnum (pos + 1), Qmouse_face, object, Qnil);
35440 e = Fnext_single_property_change
35441 (position, Qmouse_face, object, Qnil);
35442 if (NILP (s))
35443 s = make_fixnum (0);
35444 if (NILP (e))
35445 e = make_fixnum (SCHARS (object));
35446 mouse_face_from_string_pos (w, hlinfo, object,
35447 XFIXNUM (s), XFIXNUM (e));
35448 hlinfo->mouse_face_past_end = false;
35449 hlinfo->mouse_face_window = window;
35450 hlinfo->mouse_face_face_id
35451 = face_at_string_position (w, object, pos, 0, &ignore,
35452 glyph->face_id, true, 0);
35453 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35454 cursor = No_Cursor;
35455 }
35456 else
35457 {
35458
35459
35460 Lisp_Object buffer UNINIT;
35461 Lisp_Object disp_string UNINIT;
35462
35463 if (STRINGP (object))
35464 {
35465
35466
35467 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
35468 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35469 pos = string_buffer_position (object, start);
35470 if (pos > 0)
35471 {
35472 mouse_face = get_char_property_and_overlay
35473 (make_fixnum (pos), Qmouse_face, w->contents, &overlay);
35474 buffer = w->contents;
35475 disp_string = object;
35476 }
35477 }
35478 else
35479 {
35480 buffer = object;
35481 disp_string = Qnil;
35482 }
35483
35484 if (!NILP (mouse_face))
35485 {
35486 Lisp_Object before, after;
35487 Lisp_Object before_string, after_string;
35488
35489
35490
35491
35492
35493
35494
35495
35496
35497
35498 Lisp_Object lim1
35499 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35500 ? Fmarker_position (w->start)
35501 : Qnil;
35502 Lisp_Object lim2
35503 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35504 ? make_fixnum (BUF_Z (XBUFFER (buffer))
35505 - w->window_end_pos)
35506 : Qnil;
35507
35508 if (NILP (overlay))
35509 {
35510
35511 before = Fprevious_single_property_change
35512 (make_fixnum (pos + 1), Qmouse_face, buffer, lim1);
35513 after = Fnext_single_property_change
35514 (make_fixnum (pos), Qmouse_face, buffer, lim2);
35515 before_string = after_string = Qnil;
35516 }
35517 else
35518 {
35519
35520 before = Foverlay_start (overlay);
35521 after = Foverlay_end (overlay);
35522 before_string = Foverlay_get (overlay, Qbefore_string);
35523 after_string = Foverlay_get (overlay, Qafter_string);
35524
35525 if (!STRINGP (before_string)) before_string = Qnil;
35526 if (!STRINGP (after_string)) after_string = Qnil;
35527 }
35528
35529 mouse_face_from_buffer_pos (window, hlinfo, pos,
35530 NILP (before)
35531 ? 1
35532 : XFIXNAT (before),
35533 NILP (after)
35534 ? BUF_Z (XBUFFER (buffer))
35535 : XFIXNAT (after),
35536 before_string, after_string,
35537 disp_string);
35538 cursor = No_Cursor;
35539 }
35540 }
35541 }
35542
35543 check_help_echo:
35544
35545
35546 if (NILP (help_echo_string)) {
35547 Lisp_Object help, overlay;
35548
35549
35550 help = overlay = Qnil;
35551 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
35552 {
35553 overlay = overlay_vec[i];
35554 help = Foverlay_get (overlay, Qhelp_echo);
35555 }
35556
35557 if (!NILP (help))
35558 {
35559 help_echo_string = help;
35560 help_echo_window = window;
35561 help_echo_object = overlay;
35562 help_echo_pos = pos;
35563 }
35564 else
35565 {
35566 Lisp_Object obj = glyph->object;
35567 ptrdiff_t charpos = glyph->charpos;
35568
35569
35570 if (STRINGP (obj)
35571 && charpos >= 0
35572 && charpos < SCHARS (obj))
35573 {
35574 help = Fget_text_property (make_fixnum (charpos),
35575 Qhelp_echo, obj);
35576 if (NILP (help))
35577 {
35578
35579
35580 struct glyph_row *r
35581 = MATRIX_ROW (w->current_matrix, vpos);
35582 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35583 ptrdiff_t p = string_buffer_position (obj, start);
35584 if (p > 0)
35585 {
35586 help = Fget_char_property (make_fixnum (p),
35587 Qhelp_echo, w->contents);
35588 if (!NILP (help))
35589 {
35590 charpos = p;
35591 obj = w->contents;
35592 }
35593 }
35594 }
35595 }
35596 else if (BUFFERP (obj)
35597 && charpos >= BEGV
35598 && charpos < ZV)
35599 help = Fget_text_property (make_fixnum (charpos), Qhelp_echo,
35600 obj);
35601
35602 if (!NILP (help))
35603 {
35604 help_echo_string = help;
35605 help_echo_window = window;
35606 help_echo_object = obj;
35607 help_echo_pos = charpos;
35608 }
35609 }
35610 }
35611
35612 #ifdef HAVE_WINDOW_SYSTEM
35613
35614 if (FRAME_WINDOW_P (f) && NILP (pointer))
35615 {
35616
35617 for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
35618 pointer = Foverlay_get (overlay_vec[i], Qpointer);
35619
35620 if (NILP (pointer))
35621 {
35622 Lisp_Object obj = glyph->object;
35623 ptrdiff_t charpos = glyph->charpos;
35624
35625
35626 if (STRINGP (obj)
35627 && charpos >= 0
35628 && charpos < SCHARS (obj))
35629 {
35630 pointer = Fget_text_property (make_fixnum (charpos),
35631 Qpointer, obj);
35632 if (NILP (pointer))
35633 {
35634
35635
35636 struct glyph_row *r
35637 = MATRIX_ROW (w->current_matrix, vpos);
35638 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35639 ptrdiff_t p = string_buffer_position (obj, start);
35640 if (p > 0)
35641 pointer = Fget_char_property (make_fixnum (p),
35642 Qpointer, w->contents);
35643 }
35644 }
35645 else if (BUFFERP (obj)
35646 && charpos >= BEGV
35647 && charpos < ZV)
35648 pointer = Fget_text_property (make_fixnum (charpos),
35649 Qpointer, obj);
35650 }
35651 }
35652 #endif
35653
35654 BEGV = obegv;
35655 ZV = ozv;
35656 current_buffer = obuf;
35657 SAFE_FREE ();
35658 }
35659
35660 set_cursor:
35661 define_frame_cursor1 (f, cursor, pointer);
35662 }
35663
35664
35665
35666
35667
35668
35669
35670 void
35671 gui_clear_window_mouse_face (struct window *w)
35672 {
35673 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
35674 Lisp_Object window;
35675
35676 block_input ();
35677 XSETWINDOW (window, w);
35678 if (EQ (window, hlinfo->mouse_face_window))
35679 clear_mouse_face (hlinfo);
35680 unblock_input ();
35681 }
35682
35683
35684
35685
35686
35687
35688 void
35689 cancel_mouse_face (struct frame *f)
35690 {
35691 Lisp_Object window;
35692 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35693
35694 window = hlinfo->mouse_face_window;
35695 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
35696 reset_mouse_highlight (hlinfo);
35697 }
35698
35699
35700
35701
35702
35703
35704
35705 #ifdef HAVE_WINDOW_SYSTEM
35706
35707
35708
35709
35710 static void
35711 expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r,
35712 enum glyph_row_area area)
35713 {
35714 struct glyph *first = row->glyphs[area];
35715 struct glyph *end = row->glyphs[area] + row->used[area];
35716 struct glyph *last;
35717 int first_x, start_x, x;
35718
35719 if (area == TEXT_AREA && row->fill_line_p)
35720
35721 draw_glyphs (w, row->x, row, area,
35722 0, row->used[area],
35723 DRAW_NORMAL_TEXT, 0);
35724 else
35725 {
35726
35727
35728
35729 start_x = window_box_left_offset (w, area);
35730 x = start_x;
35731 if (area == TEXT_AREA)
35732 x += row->x;
35733
35734
35735 while (first < end
35736 && x + first->pixel_width < r->x)
35737 {
35738 x += first->pixel_width;
35739 ++first;
35740 }
35741
35742
35743 last = first;
35744 first_x = x;
35745
35746
35747
35748 int r_end = r->x + r->width;
35749 while (last < end && x < r_end)
35750 {
35751 x += last->pixel_width;
35752 ++last;
35753 }
35754
35755
35756 if (last > first)
35757 draw_glyphs (w, first_x - start_x, row, area,
35758 first - row->glyphs[area], last - row->glyphs[area],
35759 DRAW_NORMAL_TEXT, 0);
35760 }
35761 }
35762
35763
35764
35765
35766
35767
35768 static bool
35769 expose_line (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r)
35770 {
35771 eassert (row->enabled_p);
35772
35773 if (row->mode_line_p || w->pseudo_window_p)
35774 draw_glyphs (w, 0, row, TEXT_AREA,
35775 0, row->used[TEXT_AREA],
35776 DRAW_NORMAL_TEXT, 0);
35777 else
35778 {
35779 if (row->used[LEFT_MARGIN_AREA])
35780 expose_area (w, row, r, LEFT_MARGIN_AREA);
35781 if (row->used[TEXT_AREA])
35782 expose_area (w, row, r, TEXT_AREA);
35783 if (row->used[RIGHT_MARGIN_AREA])
35784 expose_area (w, row, r, RIGHT_MARGIN_AREA);
35785 draw_row_fringe_bitmaps (w, row);
35786 }
35787
35788 return row->mouse_face_p;
35789 }
35790
35791
35792
35793
35794
35795
35796
35797
35798
35799
35800 static void
35801 expose_overlaps (struct window *w,
35802 struct glyph_row *first_overlapping_row,
35803 struct glyph_row *last_overlapping_row,
35804 const Emacs_Rectangle *r)
35805 {
35806 struct glyph_row *row;
35807
35808 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
35809 if (row->overlapping_p)
35810 {
35811 eassert (row->enabled_p && !row->mode_line_p);
35812
35813 row->clip = r;
35814 if (row->used[LEFT_MARGIN_AREA])
35815 gui_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
35816
35817 if (row->used[TEXT_AREA])
35818 gui_fix_overlapping_area (w, row, TEXT_AREA, OVERLAPS_BOTH);
35819
35820 if (row->used[RIGHT_MARGIN_AREA])
35821 gui_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
35822 row->clip = NULL;
35823 }
35824 }
35825
35826
35827
35828
35829 static bool
35830 phys_cursor_in_rect_p (struct window *w, const Emacs_Rectangle *r)
35831 {
35832 Emacs_Rectangle cr, result;
35833 struct glyph *cursor_glyph;
35834 struct glyph_row *row;
35835
35836 if (w->phys_cursor.vpos >= 0
35837 && w->phys_cursor.vpos < w->current_matrix->nrows
35838 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
35839 row->enabled_p)
35840 && row->cursor_in_fringe_p)
35841 {
35842
35843 cr.x = window_box_right_offset (w,
35844 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
35845 ? RIGHT_MARGIN_AREA
35846 : TEXT_AREA));
35847 cr.y = row->y;
35848 cr.width = WINDOW_RIGHT_FRINGE_WIDTH (w);
35849 cr.height = row->height;
35850 return gui_intersect_rectangles (&cr, r, &result);
35851 }
35852
35853 cursor_glyph = get_phys_cursor_glyph (w);
35854 if (cursor_glyph)
35855 {
35856
35857
35858 cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
35859 cr.y = w->phys_cursor.y;
35860 cr.width = cursor_glyph->pixel_width;
35861 cr.height = w->phys_cursor_height;
35862
35863
35864 return gui_intersect_rectangles (&cr, r, &result);
35865 }
35866
35867 return false;
35868 }
35869
35870
35871
35872
35873
35874
35875 void
35876 gui_draw_vertical_border (struct window *w)
35877 {
35878 struct frame *f = XFRAME (WINDOW_FRAME (w));
35879
35880
35881
35882
35883
35884
35885
35886
35887
35888 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) || FRAME_RIGHT_DIVIDER_WIDTH (f))
35889 return;
35890
35891
35892
35893
35894 if (!WINDOW_RIGHTMOST_P (w)
35895 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
35896 {
35897 int x0, x1, y0, y1;
35898
35899 window_box_edges (w, &x0, &y0, &x1, &y1);
35900 y1 -= 1;
35901
35902 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
35903 x1 -= 1;
35904
35905 FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
35906 }
35907
35908 if (!WINDOW_LEFTMOST_P (w)
35909 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
35910 {
35911 int x0, x1, y0, y1;
35912
35913 window_box_edges (w, &x0, &y0, &x1, &y1);
35914 y1 -= 1;
35915
35916 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
35917 x0 -= 1;
35918
35919 FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
35920 }
35921 }
35922
35923
35924
35925
35926 void
35927 gui_draw_right_divider (struct window *w)
35928 {
35929 struct frame *f = WINDOW_XFRAME (w);
35930
35931 if (w->mini || w->pseudo_window_p)
35932 return;
35933 else if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
35934 {
35935 int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
35936 int x1 = WINDOW_RIGHT_EDGE_X (w);
35937 int y0 = WINDOW_TOP_EDGE_Y (w);
35938 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
35939
35940
35941
35942 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
35943 && !NILP (w->parent)
35944 && WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (w->parent))
35945 && !NILP (w->next))
35946 y1 -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
35947
35948 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
35949 }
35950 }
35951
35952 static void
35953 gui_draw_bottom_divider (struct window *w)
35954 {
35955 struct frame *f = XFRAME (WINDOW_FRAME (w));
35956
35957 if (w->mini || w->pseudo_window_p)
35958 return;
35959 else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
35960 {
35961 int x0 = WINDOW_LEFT_EDGE_X (w);
35962 int x1 = WINDOW_RIGHT_EDGE_X (w);
35963 int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
35964 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
35965 struct window *p = !NILP (w->parent) ? XWINDOW (w->parent) : NULL;
35966
35967
35968
35969 if (WINDOW_RIGHT_DIVIDER_WIDTH (w)
35970 && p
35971 && ((WINDOW_VERTICAL_COMBINATION_P (p)
35972 && !NILP (w->next))
35973 || (WINDOW_HORIZONTAL_COMBINATION_P (p)
35974 && NILP (w->next)
35975 && !NILP (p->parent)
35976 && WINDOW_VERTICAL_COMBINATION_P (XWINDOW (p->parent))
35977 && !NILP (XWINDOW (p->parent)->next))))
35978 x1 -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
35979
35980 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
35981 }
35982 }
35983
35984
35985
35986
35987
35988
35989 static bool
35990 expose_window (struct window *w, const Emacs_Rectangle *fr)
35991 {
35992 struct frame *f = XFRAME (w->frame);
35993 Emacs_Rectangle wr, r;
35994 bool mouse_face_overwritten_p = false;
35995
35996
35997
35998
35999
36000 if (w->current_matrix == NULL)
36001 return false;
36002
36003
36004
36005
36006 if (w->must_be_updated_p)
36007 {
36008 SET_FRAME_GARBAGED (f);
36009 return false;
36010 }
36011
36012
36013 wr.x = WINDOW_LEFT_EDGE_X (w);
36014 wr.y = WINDOW_TOP_EDGE_Y (w);
36015 wr.width = WINDOW_PIXEL_WIDTH (w);
36016 wr.height = WINDOW_PIXEL_HEIGHT (w);
36017
36018 if (gui_intersect_rectangles (fr, &wr, &r))
36019 {
36020 int yb = window_text_bottom_y (w);
36021 struct glyph_row *row;
36022 struct glyph_row *first_overlapping_row, *last_overlapping_row;
36023
36024 redisplay_trace ("expose_window (%d, %d, %u, %u)\n",
36025 r.x, r.y, r.width, r.height);
36026
36027
36028 r.x -= WINDOW_LEFT_EDGE_X (w);
36029 r.y -= WINDOW_TOP_EDGE_Y (w);
36030
36031
36032 bool cursor_cleared_p = (!w->pseudo_window_p
36033 && phys_cursor_in_rect_p (w, &r));
36034 if (cursor_cleared_p)
36035 gui_clear_cursor (w);
36036
36037
36038
36039
36040
36041
36042 bool phys_cursor_on_p = w->phys_cursor_on_p;
36043
36044
36045
36046
36047 int r_bottom = r.y + r.height;
36048
36049
36050
36051
36052
36053 bool buffer_changed = false;
36054 struct buffer *oldbuf = current_buffer;
36055 if (!w->pseudo_window_p)
36056 {
36057 set_buffer_internal_1 (XBUFFER (w->contents));
36058 buffer_changed = true;
36059 }
36060
36061
36062 first_overlapping_row = last_overlapping_row = NULL;
36063 for (row = w->current_matrix->rows;
36064 row->enabled_p;
36065 ++row)
36066 {
36067 int y0 = row->y;
36068 int y1 = MATRIX_ROW_BOTTOM_Y (row);
36069
36070 if ((y0 >= r.y && y0 < r_bottom)
36071 || (y1 > r.y && y1 < r_bottom)
36072 || (r.y >= y0 && r.y < y1)
36073 || (r_bottom > y0 && r_bottom < y1))
36074 {
36075
36076
36077 if (row->overlapping_p && !row->mode_line_p)
36078 {
36079 if (first_overlapping_row == NULL)
36080 first_overlapping_row = row;
36081 last_overlapping_row = row;
36082 }
36083
36084 row->clip = fr;
36085 if (expose_line (w, row, &r))
36086 mouse_face_overwritten_p = true;
36087 row->clip = NULL;
36088 }
36089 else if (row->overlapping_p)
36090 {
36091
36092 if (y0 < r.y
36093 ? y0 + row->phys_height > r.y
36094 : y0 + row->ascent - row->phys_ascent < r.y +r.height)
36095 {
36096 if (first_overlapping_row == NULL)
36097 first_overlapping_row = row;
36098 last_overlapping_row = row;
36099 }
36100 }
36101
36102 if (y1 >= yb)
36103 break;
36104 }
36105
36106 if (buffer_changed)
36107 set_buffer_internal_1 (oldbuf);
36108
36109
36110 if (window_wants_mode_line (w)
36111 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
36112 row->enabled_p)
36113 && row->y < r_bottom)
36114 {
36115 if (expose_line (w, row, &r))
36116 mouse_face_overwritten_p = true;
36117 }
36118
36119 if (!w->pseudo_window_p)
36120 {
36121
36122 if (first_overlapping_row)
36123 expose_overlaps (w, first_overlapping_row, last_overlapping_row,
36124 fr);
36125
36126
36127 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36128 gui_draw_right_divider (w);
36129 else
36130 gui_draw_vertical_border (w);
36131
36132 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36133 gui_draw_bottom_divider (w);
36134
36135
36136 if (cursor_cleared_p
36137 || (phys_cursor_on_p && !w->phys_cursor_on_p))
36138 update_window_cursor (w, true);
36139 }
36140 }
36141
36142 return mouse_face_overwritten_p;
36143 }
36144
36145
36146
36147
36148
36149
36150
36151 static bool
36152 expose_window_tree (struct window *w, const Emacs_Rectangle *r)
36153 {
36154 struct frame *f = XFRAME (w->frame);
36155 bool mouse_face_overwritten_p = false;
36156
36157 while (w && !FRAME_GARBAGED_P (f))
36158 {
36159 mouse_face_overwritten_p
36160 |= (WINDOWP (w->contents)
36161 ? expose_window_tree (XWINDOW (w->contents), r)
36162 : expose_window (w, r));
36163
36164 w = NILP (w->next) ? NULL : XWINDOW (w->next);
36165 }
36166
36167 return mouse_face_overwritten_p;
36168 }
36169
36170
36171
36172
36173
36174
36175
36176
36177 void
36178 expose_frame (struct frame *f, int x, int y, int w, int h)
36179 {
36180 Emacs_Rectangle r;
36181 bool mouse_face_overwritten_p = false;
36182
36183 if (FRAME_GARBAGED_P (f))
36184 {
36185 redisplay_trace ("expose_frame garbaged\n");
36186 return;
36187 }
36188
36189
36190
36191
36192 if (FRAME_FACE_CACHE (f) == NULL
36193 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
36194 {
36195 redisplay_trace ("expose_frame no faces\n");
36196 return;
36197 }
36198
36199 if (w == 0 || h == 0)
36200 {
36201 r.x = r.y = 0;
36202 r.width = FRAME_TEXT_WIDTH (f);
36203 r.height = FRAME_TEXT_HEIGHT (f);
36204 }
36205 else
36206 {
36207 r.x = x;
36208 r.y = y;
36209 r.width = w;
36210 r.height = h;
36211 }
36212
36213 redisplay_trace ("expose_frame (%d, %d, %u, %u)\n",
36214 r.x, r.y, r.width, r.height);
36215 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
36216
36217 if (WINDOWP (f->tab_bar_window))
36218 mouse_face_overwritten_p
36219 |= expose_window (XWINDOW (f->tab_bar_window), &r);
36220
36221 #ifndef HAVE_EXT_TOOL_BAR
36222 if (WINDOWP (f->tool_bar_window))
36223 mouse_face_overwritten_p
36224 |= expose_window (XWINDOW (f->tool_bar_window), &r);
36225 #endif
36226
36227 #ifdef HAVE_X_WINDOWS
36228 #ifndef MSDOS
36229 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
36230 if (WINDOWP (f->menu_bar_window))
36231 mouse_face_overwritten_p
36232 |= expose_window (XWINDOW (f->menu_bar_window), &r);
36233 #endif
36234 #endif
36235 #endif
36236
36237
36238
36239
36240
36241
36242
36243
36244
36245
36246
36247
36248
36249
36250 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
36251 {
36252 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
36253 if (f == hlinfo->mouse_face_mouse_frame)
36254 {
36255 int mouse_x = hlinfo->mouse_face_mouse_x;
36256 int mouse_y = hlinfo->mouse_face_mouse_y;
36257 clear_mouse_face (hlinfo);
36258 note_mouse_highlight (f, mouse_x, mouse_y);
36259 }
36260 }
36261 }
36262
36263
36264
36265
36266
36267
36268
36269 bool
36270 gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
36271 Emacs_Rectangle *result)
36272 {
36273 const Emacs_Rectangle *left, *right;
36274 const Emacs_Rectangle *upper, *lower;
36275 bool intersection_p = false;
36276
36277
36278 if (r1->x < r2->x)
36279 left = r1, right = r2;
36280 else
36281 left = r2, right = r1;
36282
36283
36284
36285 if (right->x <= left->x + left->width)
36286 {
36287 result->x = right->x;
36288
36289
36290
36291 result->width = (min (left->x + left->width, right->x + right->width)
36292 - result->x);
36293
36294
36295 if (r1->y < r2->y)
36296 upper = r1, lower = r2;
36297 else
36298 upper = r2, lower = r1;
36299
36300
36301
36302 if (lower->y <= upper->y + upper->height)
36303 {
36304 result->y = lower->y;
36305
36306
36307
36308 result->height = (min (lower->y + lower->height,
36309 upper->y + upper->height)
36310 - result->y);
36311 intersection_p = true;
36312 }
36313 }
36314
36315 return intersection_p;
36316 }
36317
36318 #endif
36319
36320
36321
36322
36323
36324
36325 void
36326 syms_of_xdisp (void)
36327 {
36328 Vwith_echo_area_save_vector = Qnil;
36329 staticpro (&Vwith_echo_area_save_vector);
36330
36331 Vmessage_stack = Qnil;
36332 staticpro (&Vmessage_stack);
36333
36334
36335 DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
36336
36337 DEFSYM (Qredisplay_internal_xC_functionx, "redisplay_internal (C function)");
36338
36339 DEFVAR_BOOL ("scroll-minibuffer-conservatively",
36340 scroll_minibuffer_conservatively,
36341 doc:
36342
36343 );
36344 scroll_minibuffer_conservatively = true;
36345
36346 DEFVAR_BOOL ("inhibit-message", inhibit_message,
36347 doc:
36348
36349
36350
36351
36352
36353 );
36354 inhibit_message = false;
36355
36356 message_dolog_marker1 = Fmake_marker ();
36357 staticpro (&message_dolog_marker1);
36358 message_dolog_marker2 = Fmake_marker ();
36359 staticpro (&message_dolog_marker2);
36360 message_dolog_marker3 = Fmake_marker ();
36361 staticpro (&message_dolog_marker3);
36362
36363 defsubr (&Sset_buffer_redisplay);
36364 #ifdef GLYPH_DEBUG
36365 defsubr (&Sdump_frame_glyph_matrix);
36366 defsubr (&Sdump_glyph_matrix);
36367 defsubr (&Sdump_glyph_row);
36368 defsubr (&Sdump_tab_bar_row);
36369 defsubr (&Sdump_tool_bar_row);
36370 defsubr (&Strace_redisplay);
36371 defsubr (&Strace_to_stderr);
36372 #endif
36373 #ifdef HAVE_WINDOW_SYSTEM
36374 defsubr (&Stab_bar_height);
36375 defsubr (&Stool_bar_height);
36376 defsubr (&Slookup_image_map);
36377 #endif
36378 defsubr (&Sline_pixel_height);
36379 defsubr (&Sformat_mode_line);
36380 defsubr (&Sinvisible_p);
36381 defsubr (&Scurrent_bidi_paragraph_direction);
36382 defsubr (&Swindow_text_pixel_size);
36383 defsubr (&Sbuffer_text_pixel_size);
36384 defsubr (&Smove_point_visually);
36385 defsubr (&Sbidi_find_overridden_directionality);
36386 defsubr (&Sdisplay__line_is_continued_p);
36387 defsubr (&Sget_display_property);
36388 defsubr (&Slong_line_optimizations_p);
36389
36390 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
36391 DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
36392 DEFSYM (Qoverriding_local_map, "overriding-local-map");
36393 DEFSYM (Qwindow_scroll_functions, "window-scroll-functions");
36394 DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
36395 DEFSYM (Qeval, "eval");
36396 DEFSYM (QCdata, ":data");
36397
36398
36399 DEFSYM (Qdisplay, "display");
36400 DEFSYM (Qspace_width, "space-width");
36401 DEFSYM (Qraise, "raise");
36402 DEFSYM (Qslice, "slice");
36403 DEFSYM (Qspace, "space");
36404 DEFSYM (Qmargin, "margin");
36405 DEFSYM (Qpointer, "pointer");
36406 DEFSYM (Qleft_margin, "left-margin");
36407 DEFSYM (Qright_margin, "right-margin");
36408 DEFSYM (Qcenter, "center");
36409 DEFSYM (Qline_height, "line-height");
36410 DEFSYM (QCalign_to, ":align-to");
36411 DEFSYM (QCrelative_width, ":relative-width");
36412 DEFSYM (QCrelative_height, ":relative-height");
36413 DEFSYM (QCeval, ":eval");
36414 DEFSYM (QCpropertize, ":propertize");
36415 DEFSYM (QCfile, ":file");
36416 DEFSYM (Qfontified, "fontified");
36417 DEFSYM (Qfontification_functions, "fontification-functions");
36418 DEFSYM (Qlong_line_optimizations_in_fontification_functions,
36419 "long-line-optimizations-in-fontification-functions");
36420
36421
36422
36423 DEFSYM (Qdisable_eval, "disable-eval");
36424
36425
36426 DEFSYM (Qtrailing_whitespace, "trailing-whitespace");
36427
36428
36429 DEFSYM (Qline_number, "line-number");
36430 DEFSYM (Qline_number_current_line, "line-number-current-line");
36431 DEFSYM (Qline_number_major_tick, "line-number-major-tick");
36432 DEFSYM (Qline_number_minor_tick, "line-number-minor-tick");
36433
36434 DEFSYM (Qdisplay_line_numbers_disable, "display-line-numbers-disable");
36435
36436
36437 DEFSYM (Qfill_column_indicator, "fill-column-indicator");
36438
36439
36440 DEFSYM (Qescape_glyph, "escape-glyph");
36441
36442
36443
36444 DEFSYM (Qnobreak_space, "nobreak-space");
36445 DEFSYM (Qnobreak_hyphen, "nobreak-hyphen");
36446
36447
36448
36449 DEFSYM (Qimage, "image");
36450
36451
36452 DEFSYM (Qtext, "text");
36453 DEFSYM (Qboth, "both");
36454 DEFSYM (Qboth_horiz, "both-horiz");
36455 DEFSYM (Qtext_image_horiz, "text-image-horiz");
36456
36457
36458 DEFSYM (QCmap, ":map");
36459 DEFSYM (QCpointer, ":pointer");
36460 DEFSYM (Qrect, "rect");
36461 DEFSYM (Qcircle, "circle");
36462 DEFSYM (Qpoly, "poly");
36463
36464 DEFSYM (Qinhibit_menubar_update, "inhibit-menubar-update");
36465
36466 DEFSYM (Qgrow_only, "grow-only");
36467 DEFSYM (Qinhibit_eval_during_redisplay, "inhibit-eval-during-redisplay");
36468 DEFSYM (Qposition, "position");
36469 DEFSYM (Qbuffer_position, "buffer-position");
36470 DEFSYM (Qobject, "object");
36471
36472
36473 DEFSYM (Qbar, "bar");
36474 DEFSYM (Qhbar, "hbar");
36475 DEFSYM (Qbox, "box");
36476 DEFSYM (Qhollow, "hollow");
36477
36478
36479 DEFSYM (Qhand, "hand");
36480 DEFSYM (Qarrow, "arrow");
36481
36482
36483 DEFSYM (Qdragging, "dragging");
36484 DEFSYM (Qdropping, "dropping");
36485 DEFSYM (Qdrag_source, "drag-source");
36486
36487 DEFSYM (Qdrag_with_mode_line, "drag-with-mode-line");
36488 DEFSYM (Qdrag_with_header_line, "drag-with-header-line");
36489 DEFSYM (Qdrag_with_tab_line, "drag-with-tab-line");
36490
36491 DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
36492
36493 list_of_error = list1 (Qerror);
36494 staticpro (&list_of_error);
36495
36496
36497
36498
36499
36500 DEFSYM (Qlast_arrow_position, "last-arrow-position");
36501 DEFSYM (Qlast_arrow_string, "last-arrow-string");
36502
36503
36504
36505 DEFSYM (Qoverlay_arrow_string, "overlay-arrow-string");
36506 DEFSYM (Qoverlay_arrow_bitmap, "overlay-arrow-bitmap");
36507
36508 echo_buffer[0] = echo_buffer[1] = Qnil;
36509 staticpro (&echo_buffer[0]);
36510 staticpro (&echo_buffer[1]);
36511
36512 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
36513 staticpro (&echo_area_buffer[0]);
36514 staticpro (&echo_area_buffer[1]);
36515
36516 DEFVAR_LISP ("messages-buffer-name", Vmessages_buffer_name,
36517 doc:
36518
36519
36520
36521 );
36522 Vmessages_buffer_name = build_string ("*Messages*");
36523
36524 mode_line_proptrans_alist = Qnil;
36525 staticpro (&mode_line_proptrans_alist);
36526 mode_line_string_list = Qnil;
36527 staticpro (&mode_line_string_list);
36528 mode_line_string_face = Qnil;
36529 staticpro (&mode_line_string_face);
36530 mode_line_string_face_prop = Qnil;
36531 staticpro (&mode_line_string_face_prop);
36532 Vmode_line_unwind_vector = Qnil;
36533 staticpro (&Vmode_line_unwind_vector);
36534
36535 DEFSYM (Qmode_line_default_help_echo, "mode-line-default-help-echo");
36536
36537 help_echo_string = Qnil;
36538 staticpro (&help_echo_string);
36539 help_echo_object = Qnil;
36540 staticpro (&help_echo_object);
36541 help_echo_window = Qnil;
36542 staticpro (&help_echo_window);
36543 previous_help_echo_string = Qnil;
36544 staticpro (&previous_help_echo_string);
36545 help_echo_pos = -1;
36546
36547 DEFSYM (Qright_to_left, "right-to-left");
36548 DEFSYM (Qleft_to_right, "left-to-right");
36549 defsubr (&Sbidi_resolved_levels);
36550
36551 #ifdef HAVE_WINDOW_SYSTEM
36552 DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
36553 doc:
36554
36555 );
36556 x_stretch_cursor_p = 0;
36557 #endif
36558
36559 DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
36560 doc:
36561 );
36562 Vshow_trailing_whitespace = Qnil;
36563
36564 DEFVAR_LISP ("mode-line-compact", Vmode_line_compact,
36565 doc:
36566
36567
36568 );
36569 Vmode_line_compact = Qnil;
36570 DEFSYM (Qlong, "long");
36571
36572 DEFVAR_LISP ("nobreak-char-display", Vnobreak_char_display,
36573 doc:
36574
36575
36576
36577
36578
36579
36580
36581
36582
36583
36584
36585 );
36586 Vnobreak_char_display = Qt;
36587
36588 DEFVAR_BOOL ("nobreak-char-ascii-display", nobreak_char_ascii_display,
36589 doc:
36590
36591
36592
36593
36594
36595
36596
36597
36598
36599
36600
36601
36602
36603
36604
36605 );
36606 nobreak_char_ascii_display = false;
36607
36608 DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
36609 doc:
36610
36611
36612 );
36613 Vvoid_text_area_pointer = Qarrow;
36614
36615 DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay,
36616 doc:
36617 );
36618 Vinhibit_redisplay = Qnil;
36619
36620 DEFVAR_LISP ("global-mode-string", Vglobal_mode_string,
36621 doc: );
36622 Vglobal_mode_string = Qnil;
36623
36624 DEFVAR_LISP ("overlay-arrow-position", Voverlay_arrow_position,
36625 doc:
36626
36627 );
36628 Voverlay_arrow_position = Qnil;
36629
36630 DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
36631 doc:
36632 );
36633 Voverlay_arrow_string = build_pure_c_string ("=>");
36634
36635 DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
36636 doc:
36637
36638 );
36639 Voverlay_arrow_variable_list
36640 = list1 (intern_c_string ("overlay-arrow-position"));
36641
36642 DEFVAR_INT ("scroll-step", emacs_scroll_step,
36643 doc:
36644
36645
36646
36647 );
36648
36649 DEFVAR_INT ("scroll-conservatively", scroll_conservatively,
36650 doc:
36651
36652
36653
36654
36655
36656
36657
36658
36659
36660 );
36661 scroll_conservatively = 0;
36662
36663 DEFVAR_INT ("scroll-margin", scroll_margin,
36664 doc:
36665
36666 );
36667 scroll_margin = 0;
36668
36669 DEFVAR_LISP ("maximum-scroll-margin", Vmaximum_scroll_margin,
36670 doc:
36671
36672
36673
36674 );
36675 Vmaximum_scroll_margin = make_float (0.25);
36676
36677 DEFVAR_LISP ("display-pixels-per-inch", Vdisplay_pixels_per_inch,
36678 doc:
36679 );
36680 Vdisplay_pixels_per_inch = make_float (72.0);
36681
36682 #ifdef GLYPH_DEBUG
36683 DEFVAR_INT ("debug-end-pos", debug_end_pos, doc: );
36684 #endif
36685
36686 DEFVAR_LISP ("truncate-partial-width-windows",
36687 Vtruncate_partial_width_windows,
36688 doc:
36689
36690
36691
36692
36693
36694
36695
36696
36697
36698
36699
36700
36701
36702
36703
36704 );
36705 Vtruncate_partial_width_windows = make_fixnum (50);
36706
36707 DEFVAR_BOOL("word-wrap-by-category", word_wrap_by_category, doc:
36708
36709
36710
36711
36712
36713
36714
36715
36716
36717
36718
36719
36720
36721 );
36722 word_wrap_by_category = false;
36723
36724 DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
36725 doc:
36726
36727 );
36728 Vline_number_display_limit = Qnil;
36729
36730 DEFVAR_INT ("line-number-display-limit-width",
36731 line_number_display_limit_width,
36732 doc:
36733
36734 );
36735 line_number_display_limit_width = 200;
36736
36737 DEFVAR_BOOL ("highlight-nonselected-windows", highlight_nonselected_windows,
36738 doc:
36739
36740 );
36741 highlight_nonselected_windows = false;
36742
36743 DEFVAR_BOOL ("multiple-frames", multiple_frames,
36744 doc:
36745
36746
36747 );
36748
36749 DEFVAR_LISP ("frame-title-format", Vframe_title_format,
36750 doc:
36751
36752
36753
36754
36755 );
36756
36757 DEFVAR_LISP ("icon-title-format", Vicon_title_format,
36758 doc:
36759
36760
36761
36762
36763
36764 );
36765
36766
36767 Lisp_Object icon_title_name_format
36768 = pure_list (empty_unibyte_string,
36769 build_pure_c_string ("%b - GNU Emacs at "),
36770 intern_c_string ("system-name"));
36771 Vicon_title_format
36772 = Vframe_title_format
36773 = pure_list (intern_c_string ("multiple-frames"),
36774 build_pure_c_string ("%b"),
36775 icon_title_name_format);
36776
36777 DEFVAR_LISP ("message-log-max", Vmessage_log_max,
36778 doc:
36779
36780 );
36781 Vmessage_log_max = make_fixnum (1000);
36782
36783 DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
36784 doc:
36785
36786
36787
36788
36789
36790
36791
36792
36793
36794
36795
36796
36797
36798 );
36799 Vwindow_scroll_functions = Qnil;
36800
36801 DEFVAR_LISP ("mouse-autoselect-window", Vmouse_autoselect_window,
36802 doc:
36803
36804
36805
36806
36807
36808
36809
36810
36811
36812
36813
36814
36815
36816
36817
36818
36819
36820 );
36821 Vmouse_autoselect_window = Qnil;
36822
36823 DEFVAR_LISP ("auto-resize-tab-bars", Vauto_resize_tab_bars,
36824 doc:
36825
36826
36827
36828
36829 );
36830 Vauto_resize_tab_bars = Qt;
36831
36832 DEFVAR_BOOL ("auto-raise-tab-bar-buttons", auto_raise_tab_bar_buttons_p,
36833 doc: );
36834 auto_raise_tab_bar_buttons_p = true;
36835
36836 DEFVAR_LISP ("auto-resize-tool-bars", Vauto_resize_tool_bars,
36837 doc:
36838
36839
36840
36841
36842 );
36843 Vauto_resize_tool_bars = Qt;
36844
36845 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", auto_raise_tool_bar_buttons_p,
36846 doc: );
36847 auto_raise_tool_bar_buttons_p = true;
36848
36849 DEFVAR_LISP ("make-cursor-line-fully-visible", Vmake_cursor_line_fully_visible,
36850 doc:
36851
36852
36853
36854
36855 );
36856 Vmake_cursor_line_fully_visible = Qt;
36857 DEFSYM (Qmake_cursor_line_fully_visible, "make-cursor-line-fully-visible");
36858
36859 DEFVAR_BOOL ("make-window-start-visible", make_window_start_visible,
36860 doc: );
36861 make_window_start_visible = false;
36862 DEFSYM (Qmake_window_start_visible, "make-window-start-visible");
36863 Fmake_variable_buffer_local (Qmake_window_start_visible);
36864
36865 DEFSYM (Qclose_tab, "close-tab");
36866 DEFVAR_LISP ("tab-bar-border", Vtab_bar_border,
36867 doc:
36868
36869
36870
36871 );
36872 Vtab_bar_border = Qinternal_border_width;
36873
36874 DEFVAR_LISP ("tab-bar-button-margin", Vtab_bar_button_margin,
36875 doc:
36876
36877
36878
36879 );
36880 Vtab_bar_button_margin = make_fixnum (DEFAULT_TAB_BAR_BUTTON_MARGIN);
36881
36882 DEFVAR_INT ("tab-bar-button-relief", tab_bar_button_relief,
36883 doc: );
36884 tab_bar_button_relief = DEFAULT_TAB_BAR_BUTTON_RELIEF;
36885
36886 DEFVAR_LISP ("tool-bar-border", Vtool_bar_border,
36887 doc:
36888
36889
36890
36891 );
36892 Vtool_bar_border = Qinternal_border_width;
36893
36894 DEFVAR_LISP ("tool-bar-button-margin", Vtool_bar_button_margin,
36895 doc:
36896
36897
36898
36899 );
36900 Vtool_bar_button_margin = make_fixnum (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
36901
36902 DEFVAR_INT ("tool-bar-button-relief", tool_bar_button_relief,
36903 doc: );
36904 tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
36905
36906 DEFVAR_LISP ("tool-bar-style", Vtool_bar_style,
36907 doc:
36908
36909
36910
36911
36912
36913
36914
36915
36916 );
36917 Vtool_bar_style = Qnil;
36918
36919 DEFVAR_INT ("tool-bar-max-label-size", tool_bar_max_label_size,
36920 doc:
36921
36922 );
36923 tool_bar_max_label_size = DEFAULT_TOOL_BAR_LABEL_SIZE;
36924
36925 DEFVAR_LISP ("fontification-functions", Vfontification_functions,
36926 doc:
36927
36928
36929
36930
36931
36932
36933
36934
36935 );
36936 Vfontification_functions = Qnil;
36937 Fmake_variable_buffer_local (Qfontification_functions);
36938
36939 DEFVAR_BOOL ("unibyte-display-via-language-environment",
36940 unibyte_display_via_language_environment,
36941 doc:
36942
36943
36944
36945
36946
36947
36948 );
36949 unibyte_display_via_language_environment = false;
36950
36951 DEFVAR_LISP ("max-mini-window-height", Vmax_mini_window_height,
36952 doc:
36953
36954
36955
36956 );
36957 Vmax_mini_window_height = make_float (0.25);
36958
36959 DEFVAR_LISP ("resize-mini-windows", Vresize_mini_windows,
36960 doc:
36961
36962
36963
36964
36965
36966
36967
36968
36969 );
36970
36971
36972
36973
36974
36975 Vresize_mini_windows = Qnil;
36976
36977 DEFVAR_LISP ("blink-cursor-alist", Vblink_cursor_alist,
36978 doc:
36979
36980
36981
36982
36983
36984
36985
36986 );
36987 Vblink_cursor_alist = Qnil;
36988
36989 DEFVAR_LISP ("auto-hscroll-mode", automatic_hscrolling,
36990 doc:
36991
36992
36993
36994 );
36995 automatic_hscrolling = Qt;
36996 DEFSYM (Qauto_hscroll_mode, "auto-hscroll-mode");
36997 DEFSYM (Qcurrent_line, "current-line");
36998
36999 DEFVAR_INT ("hscroll-margin", hscroll_margin,
37000 doc:
37001 );
37002 hscroll_margin = 5;
37003
37004 DEFVAR_LISP ("hscroll-step", Vhscroll_step,
37005 doc:
37006
37007
37008
37009
37010
37011
37012
37013
37014
37015
37016
37017
37018
37019 );
37020 Vhscroll_step = make_fixnum (0);
37021
37022 DEFVAR_BOOL ("message-truncate-lines", message_truncate_lines,
37023 doc:
37024 );
37025 message_truncate_lines = false;
37026
37027 DEFVAR_LISP ("menu-bar-update-hook", Vmenu_bar_update_hook,
37028 doc:
37029
37030
37031 );
37032 Vmenu_bar_update_hook = Qnil;
37033
37034 DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,
37035 doc:
37036 );
37037 Vmenu_updating_frame = Qnil;
37038
37039 DEFVAR_BOOL ("inhibit-menubar-update", inhibit_menubar_update,
37040 doc: );
37041 inhibit_menubar_update = false;
37042
37043 DEFVAR_LISP ("wrap-prefix", Vwrap_prefix,
37044 doc:
37045
37046
37047
37048
37049
37050
37051 );
37052 Vwrap_prefix = Qnil;
37053 DEFSYM (Qwrap_prefix, "wrap-prefix");
37054 Fmake_variable_buffer_local (Qwrap_prefix);
37055
37056 DEFVAR_LISP ("line-prefix", Vline_prefix,
37057 doc:
37058
37059
37060
37061
37062
37063
37064 );
37065 Vline_prefix = Qnil;
37066 DEFSYM (Qline_prefix, "line-prefix");
37067 Fmake_variable_buffer_local (Qline_prefix);
37068
37069 DEFVAR_LISP ("display-line-numbers", Vdisplay_line_numbers,
37070 doc:
37071
37072
37073
37074
37075
37076
37077
37078
37079
37080
37081
37082
37083
37084
37085
37086
37087
37088
37089
37090
37091
37092
37093 );
37094 Vdisplay_line_numbers = Qnil;
37095 DEFSYM (Qdisplay_line_numbers, "display-line-numbers");
37096 Fmake_variable_buffer_local (Qdisplay_line_numbers);
37097 DEFSYM (Qrelative, "relative");
37098 DEFSYM (Qvisual, "visual");
37099
37100 DEFVAR_LISP ("display-line-numbers-width", Vdisplay_line_numbers_width,
37101 doc:
37102
37103
37104
37105 );
37106 Vdisplay_line_numbers_width = Qnil;
37107 DEFSYM (Qdisplay_line_numbers_width, "display-line-numbers-width");
37108 Fmake_variable_buffer_local (Qdisplay_line_numbers_width);
37109
37110 DEFVAR_LISP ("display-line-numbers-current-absolute",
37111 Vdisplay_line_numbers_current_absolute,
37112 doc:
37113
37114 );
37115 Vdisplay_line_numbers_current_absolute = Qt;
37116
37117 DEFVAR_BOOL ("display-line-numbers-widen", display_line_numbers_widen,
37118 doc: );
37119 display_line_numbers_widen = false;
37120 DEFSYM (Qdisplay_line_numbers_widen, "display-line-numbers-widen");
37121 Fmake_variable_buffer_local (Qdisplay_line_numbers_widen);
37122
37123 DEFVAR_INT ("display-line-numbers-offset", display_line_numbers_offset,
37124 doc:
37125
37126
37127 );
37128 display_line_numbers_offset = 0;
37129 DEFSYM (Qdisplay_line_numbers_offset, "display-line-numbers-offset");
37130 Fmake_variable_buffer_local (Qdisplay_line_numbers_offset);
37131
37132 DEFVAR_BOOL ("display-fill-column-indicator", display_fill_column_indicator,
37133 doc:
37134
37135
37136 );
37137 display_fill_column_indicator = false;
37138 DEFSYM (Qdisplay_fill_column_indicator, "display-fill-column-indicator");
37139 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator);
37140
37141 DEFVAR_LISP ("display-fill-column-indicator-column", Vdisplay_fill_column_indicator_column,
37142 doc:
37143
37144
37145
37146 );
37147 Vdisplay_fill_column_indicator_column = Qt;
37148 DEFSYM (Qdisplay_fill_column_indicator_column, "display-fill-column-indicator-column");
37149 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_column);
37150
37151 DEFVAR_LISP ("display-fill-column-indicator-character", Vdisplay_fill_column_indicator_character,
37152 doc:
37153
37154
37155 );
37156 Vdisplay_fill_column_indicator_character = Qnil;
37157 DEFSYM (Qdisplay_fill_column_indicator_character, "display-fill-column-indicator-character");
37158 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_character);
37159
37160 DEFVAR_INT ("display-line-numbers-major-tick", display_line_numbers_major_tick,
37161 doc:
37162
37163
37164 );
37165 display_line_numbers_major_tick = 0;
37166
37167 DEFVAR_INT ("display-line-numbers-minor-tick", display_line_numbers_minor_tick,
37168 doc:
37169
37170
37171 );
37172 display_line_numbers_minor_tick = 0;
37173
37174 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
37175 doc: );
37176 inhibit_eval_during_redisplay = false;
37177
37178 DEFVAR_BOOL ("inhibit-free-realized-faces", inhibit_free_realized_faces,
37179 doc: );
37180 inhibit_free_realized_faces = false;
37181
37182 DEFVAR_BOOL ("inhibit-bidi-mirroring", inhibit_bidi_mirroring,
37183 doc:
37184
37185 );
37186 inhibit_bidi_mirroring = false;
37187
37188 DEFVAR_BOOL ("bidi-inhibit-bpa", bidi_inhibit_bpa,
37189 doc:
37190
37191
37192
37193 );
37194 bidi_inhibit_bpa = false;
37195
37196 #ifdef GLYPH_DEBUG
37197 DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
37198 doc: );
37199 inhibit_try_window_id = false;
37200
37201 DEFVAR_BOOL ("inhibit-try-window-reusing", inhibit_try_window_reusing,
37202 doc: );
37203 inhibit_try_window_reusing = false;
37204
37205 DEFVAR_BOOL ("inhibit-try-cursor-movement", inhibit_try_cursor_movement,
37206 doc: );
37207 inhibit_try_cursor_movement = false;
37208 #endif
37209
37210 DEFVAR_INT ("overline-margin", overline_margin,
37211 doc:
37212
37213 );
37214 overline_margin = 2;
37215
37216 DEFVAR_INT ("underline-minimum-offset",
37217 underline_minimum_offset,
37218 doc:
37219
37220
37221
37222 );
37223 underline_minimum_offset = 1;
37224 DEFSYM (Qunderline_minimum_offset, "underline-minimum-offset");
37225
37226 DEFVAR_BOOL ("display-hourglass", display_hourglass_p,
37227 doc:
37228
37229 );
37230 display_hourglass_p = true;
37231
37232 DEFVAR_LISP ("hourglass-delay", Vhourglass_delay,
37233 doc: );
37234 Vhourglass_delay = make_fixnum (DEFAULT_HOURGLASS_DELAY);
37235
37236 #ifdef HAVE_WINDOW_SYSTEM
37237 hourglass_atimer = NULL;
37238 hourglass_shown_p = false;
37239 #endif
37240
37241
37242 DEFSYM (Qglyphless_char, "glyphless-char");
37243
37244
37245 DEFSYM (Qhex_code, "hex-code");
37246 DEFSYM (Qempty_box, "empty-box");
37247 DEFSYM (Qthin_space, "thin-space");
37248 DEFSYM (Qzero_width, "zero-width");
37249
37250 DEFVAR_LISP ("pre-redisplay-function", Vpre_redisplay_function,
37251 doc:
37252
37253
37254 );
37255 Vpre_redisplay_function = intern ("ignore");
37256
37257
37258 DEFSYM (Qglyphless_char_display, "glyphless-char-display");
37259 Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_fixnum (1));
37260
37261 DEFVAR_LISP ("glyphless-char-display", Vglyphless_char_display,
37262 doc:
37263
37264
37265
37266
37267
37268
37269
37270
37271
37272
37273
37274
37275
37276
37277
37278
37279
37280
37281
37282
37283
37284
37285
37286 );
37287 Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
37288 Fset_char_table_extra_slot (Vglyphless_char_display, make_fixnum (0),
37289 Qempty_box);
37290
37291 DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
37292 doc: );
37293 Vdebug_on_message = Qnil;
37294
37295 DEFVAR_LISP ("set-message-function", Vset_message_function,
37296 doc:
37297
37298
37299
37300
37301
37302
37303
37304
37305
37306 );
37307 Vset_message_function = Qnil;
37308
37309 DEFSYM (Qdont_clear_message, "dont-clear-message");
37310 DEFVAR_LISP ("clear-message-function", Vclear_message_function,
37311 doc:
37312
37313
37314
37315
37316
37317
37318
37319
37320
37321
37322 );
37323 Vclear_message_function = Qnil;
37324
37325 DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
37326 doc:
37327 );
37328 Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL);
37329
37330 DEFVAR_LISP ("redisplay--mode-lines-cause", Vredisplay__mode_lines_cause,
37331 doc:
37332 );
37333 Vredisplay__mode_lines_cause = Fmake_hash_table (0, NULL);
37334
37335 DEFVAR_BOOL ("redisplay--inhibit-bidi", redisplay__inhibit_bidi,
37336 doc: );
37337
37338
37339 redisplay__inhibit_bidi = true;
37340
37341 DEFVAR_BOOL ("display-raw-bytes-as-hex", display_raw_bytes_as_hex,
37342 doc:
37343
37344 );
37345 display_raw_bytes_as_hex = false;
37346
37347 DEFVAR_BOOL ("mouse-fine-grained-tracking", mouse_fine_grained_tracking,
37348 doc:
37349
37350 );
37351 mouse_fine_grained_tracking = false;
37352
37353 DEFVAR_BOOL ("tab-bar--dragging-in-progress", tab_bar__dragging_in_progress,
37354 doc: );
37355 tab_bar__dragging_in_progress = false;
37356
37357 DEFVAR_BOOL ("redisplay-skip-initial-frame", redisplay_skip_initial_frame,
37358 doc:
37359
37360
37361
37362 );
37363 redisplay_skip_initial_frame = true;
37364
37365 DEFVAR_BOOL ("redisplay-skip-fontification-on-input",
37366 redisplay_skip_fontification_on_input,
37367 doc:
37368
37369
37370
37371
37372
37373
37374
37375 );
37376 redisplay_skip_fontification_on_input = false;
37377
37378 DEFVAR_BOOL ("redisplay-adhoc-scroll-in-resize-mini-windows",
37379 redisplay_adhoc_scroll_in_resize_mini_windows,
37380 doc:
37381
37382 );
37383
37384 redisplay_adhoc_scroll_in_resize_mini_windows = true;
37385
37386 DEFVAR_BOOL ("composition-break-at-point", composition_break_at_point,
37387 doc:
37388
37389 );
37390 composition_break_at_point = false;
37391
37392 DEFVAR_INT ("max-redisplay-ticks", max_redisplay_ticks,
37393 doc:
37394
37395
37396
37397
37398
37399
37400
37401
37402
37403
37404
37405 );
37406 max_redisplay_ticks = 0;
37407 }
37408
37409
37410
37411
37412 void
37413 init_xdisp (void)
37414 {
37415 CHARPOS (this_line_start_pos) = 0;
37416
37417 echo_area_window = minibuf_window;
37418
37419 if (!noninteractive)
37420 {
37421 struct window *m = XWINDOW (minibuf_window);
37422 Lisp_Object frame = m->frame;
37423 struct frame *f = XFRAME (frame);
37424 Lisp_Object root = FRAME_ROOT_WINDOW (f);
37425 struct window *r = XWINDOW (root);
37426 int i;
37427
37428 r->top_line = FRAME_TOP_MARGIN (f);
37429 r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
37430 r->total_cols = FRAME_COLS (f);
37431 r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
37432 r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_TOP_MARGIN (f);
37433 r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
37434
37435 m->top_line = FRAME_TOTAL_LINES (f) - 1;
37436 m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
37437 m->total_cols = FRAME_COLS (f);
37438 m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
37439 m->total_lines = 1;
37440 m->pixel_height = m->total_lines * FRAME_LINE_HEIGHT (f);
37441
37442 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
37443 scratch_glyph_row.glyphs[TEXT_AREA + 1]
37444 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
37445
37446
37447 for (i = 0; i < 3; ++i)
37448 default_invis_vector[i] = make_fixnum ('.');
37449 }
37450
37451 {
37452
37453
37454 int size = 100;
37455 mode_line_noprop_buf = xmalloc (size);
37456 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
37457 mode_line_noprop_ptr = mode_line_noprop_buf;
37458 mode_line_target = MODE_LINE_DISPLAY;
37459 }
37460
37461 help_echo_showing_p = false;
37462 }
37463
37464 #ifdef HAVE_WINDOW_SYSTEM
37465
37466
37467
37468
37469
37470 static void
37471 show_hourglass (struct atimer *timer)
37472 {
37473
37474
37475
37476 hourglass_atimer = NULL;
37477
37478 if (!hourglass_shown_p)
37479 {
37480 Lisp_Object tail, frame;
37481
37482 block_input ();
37483
37484 FOR_EACH_FRAME (tail, frame)
37485 {
37486 struct frame *f = XFRAME (frame);
37487
37488 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37489 && FRAME_RIF (f)->show_hourglass)
37490 FRAME_RIF (f)->show_hourglass (f);
37491 }
37492
37493 hourglass_shown_p = true;
37494 unblock_input ();
37495 }
37496 }
37497
37498
37499
37500 void
37501 start_hourglass (void)
37502 {
37503 struct timespec delay;
37504
37505 cancel_hourglass ();
37506
37507 if (FIXNUMP (Vhourglass_delay)
37508 && XFIXNUM (Vhourglass_delay) > 0)
37509 delay = make_timespec (min (XFIXNUM (Vhourglass_delay),
37510 TYPE_MAXIMUM (time_t)),
37511 0);
37512 else if (FLOATP (Vhourglass_delay)
37513 && XFLOAT_DATA (Vhourglass_delay) > 0)
37514 delay = dtotimespec (XFLOAT_DATA (Vhourglass_delay));
37515 else
37516 delay = make_timespec (DEFAULT_HOURGLASS_DELAY, 0);
37517
37518 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
37519 show_hourglass, NULL);
37520 }
37521
37522
37523
37524
37525 void
37526 cancel_hourglass (void)
37527 {
37528 if (hourglass_atimer)
37529 {
37530 cancel_atimer (hourglass_atimer);
37531 hourglass_atimer = NULL;
37532 }
37533
37534 if (hourglass_shown_p)
37535 {
37536 Lisp_Object tail, frame;
37537
37538 block_input ();
37539
37540 FOR_EACH_FRAME (tail, frame)
37541 {
37542 struct frame *f = XFRAME (frame);
37543
37544 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37545 && FRAME_RIF (f)->hide_hourglass)
37546 FRAME_RIF (f)->hide_hourglass (f);
37547 #ifdef HAVE_NTGUI
37548
37549 else if (!FRAME_W32_P (f))
37550 w32_arrow_cursor ();
37551 #endif
37552 }
37553
37554 hourglass_shown_p = false;
37555 unblock_input ();
37556 }
37557 }
37558
37559
37560
37561
37562
37563
37564
37565
37566 static int
37567 adjust_glyph_width_for_mouse_face (struct glyph *g, struct glyph_row *row,
37568 struct window *w,
37569 struct face *original_face,
37570 struct face *mouse_face)
37571 {
37572 int sum = 0;
37573
37574 bool do_left_box_p = g->left_box_line_p;
37575 bool do_right_box_p = g->right_box_line_p;
37576
37577
37578
37579 if (g->type == IMAGE_GLYPH)
37580 {
37581 if (!row->reversed_p)
37582 {
37583 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37584 g->u.img_id);
37585 do_left_box_p = g->left_box_line_p &&
37586 g->slice.img.x == 0;
37587 do_right_box_p = g->right_box_line_p &&
37588 g->slice.img.x + g->slice.img.width == img->width;
37589 }
37590 else
37591 {
37592 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37593 g->u.img_id);
37594 do_left_box_p = g->left_box_line_p &&
37595 g->slice.img.x + g->slice.img.width == img->width;
37596 do_right_box_p = g->right_box_line_p &&
37597 g->slice.img.x == 0;
37598 }
37599 }
37600
37601
37602 if (do_left_box_p)
37603 sum -= max (0, original_face->box_vertical_line_width);
37604
37605
37606 if (do_right_box_p)
37607 sum -= max (0, original_face->box_vertical_line_width);
37608
37609 if (g->left_box_line_p)
37610 sum += max (0, mouse_face->box_vertical_line_width);
37611 if (g->right_box_line_p)
37612 sum += max (0, mouse_face->box_vertical_line_width);
37613
37614 return sum;
37615 }
37616
37617
37618
37619
37620
37621
37622
37623
37624
37625 static void
37626 get_cursor_offset_for_mouse_face (struct window *w, struct glyph_row *row,
37627 int *offset)
37628 {
37629 int sum = 0;
37630
37631 if (row->mode_line_p)
37632 return;
37633
37634 block_input ();
37635
37636 struct frame *f = WINDOW_XFRAME (w);
37637 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
37638 struct glyph *start, *end;
37639 struct face *mouse_face = FACE_FROM_ID (f, hlinfo->mouse_face_face_id);
37640 int hpos = w->phys_cursor.hpos;
37641 end = &row->glyphs[TEXT_AREA][hpos];
37642
37643 if (!row->reversed_p)
37644 {
37645 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37646 hlinfo->mouse_face_beg_row)
37647 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_beg_col];
37648 else
37649 start = row->glyphs[TEXT_AREA];
37650 }
37651 else
37652 {
37653 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37654 hlinfo->mouse_face_end_row)
37655 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_end_col];
37656 else
37657 start = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
37658 }
37659
37660
37661
37662
37663 for ( ; row->reversed_p ? start > end : start < end;
37664 row->reversed_p ? --start : ++start)
37665 sum += adjust_glyph_width_for_mouse_face (start, row, w,
37666 FACE_FROM_ID (f, start->face_id),
37667 mouse_face);
37668
37669 if (row->reversed_p)
37670 sum = -sum;
37671
37672 *offset = sum;
37673
37674 unblock_input ();
37675 }
37676 #endif